@acorex/charts 21.0.3-next.3 → 21.0.3-next.31

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.
Files changed (31) hide show
  1. package/{types/acorex-charts-bar-chart.d.ts → bar-chart/index.d.ts} +3 -28
  2. package/{types/acorex-charts-donut-chart.d.ts → donut-chart/index.d.ts} +8 -22
  3. package/fesm2022/acorex-charts-bar-chart.mjs +66 -91
  4. package/fesm2022/acorex-charts-bar-chart.mjs.map +1 -1
  5. package/fesm2022/acorex-charts-chart-legend.mjs +13 -13
  6. package/fesm2022/acorex-charts-chart-legend.mjs.map +1 -1
  7. package/fesm2022/acorex-charts-chart-tooltip.mjs +11 -11
  8. package/fesm2022/acorex-charts-chart-tooltip.mjs.map +1 -1
  9. package/fesm2022/acorex-charts-donut-chart.mjs +94 -101
  10. package/fesm2022/acorex-charts-donut-chart.mjs.map +1 -1
  11. package/fesm2022/acorex-charts-funnel-chart.mjs +19 -19
  12. package/fesm2022/acorex-charts-funnel-chart.mjs.map +1 -1
  13. package/fesm2022/acorex-charts-gauge-chart.mjs +64 -45
  14. package/fesm2022/acorex-charts-gauge-chart.mjs.map +1 -1
  15. package/fesm2022/acorex-charts-heatmap-chart.mjs +16 -19
  16. package/fesm2022/acorex-charts-heatmap-chart.mjs.map +1 -1
  17. package/fesm2022/acorex-charts-hierarchy-chart.mjs +39 -80
  18. package/fesm2022/acorex-charts-hierarchy-chart.mjs.map +1 -1
  19. package/fesm2022/acorex-charts-line-chart.mjs +42 -109
  20. package/fesm2022/acorex-charts-line-chart.mjs.map +1 -1
  21. package/fesm2022/acorex-charts.mjs +69 -5
  22. package/fesm2022/acorex-charts.mjs.map +1 -1
  23. package/{types/acorex-charts-funnel-chart.d.ts → funnel-chart/index.d.ts} +3 -25
  24. package/{types/acorex-charts-gauge-chart.d.ts → gauge-chart/index.d.ts} +6 -21
  25. package/{types/acorex-charts-heatmap-chart.d.ts → heatmap-chart/index.d.ts} +2 -28
  26. package/{types/acorex-charts-hierarchy-chart.d.ts → hierarchy-chart/index.d.ts} +2 -27
  27. package/{types/acorex-charts.d.ts → index.d.ts} +52 -2
  28. package/{types/acorex-charts-line-chart.d.ts → line-chart/index.d.ts} +2 -38
  29. package/package.json +15 -16
  30. /package/{types/acorex-charts-chart-legend.d.ts → chart-legend/index.d.ts} +0 -0
  31. /package/{types/acorex-charts-chart-tooltip.d.ts → chart-tooltip/index.d.ts} +0 -0
@@ -1,4 +1,3 @@
1
- import * as _acorex_charts_bar_chart from '@acorex/charts/bar-chart';
2
1
  import * as _acorex_charts from '@acorex/charts';
3
2
  import { NXNativeEvent, AXAnimationEasing, AXChartComponent, AXChartComponentBase } from '@acorex/charts';
4
3
  import * as d3 from 'd3';
@@ -72,6 +71,7 @@ interface AXBarChartOption {
72
71
  yAxisLabel?: string;
73
72
  rotateXAxisLabels?: boolean | 'auto';
74
73
  showTooltip?: boolean;
74
+ /** Percent of band width used by each bar (0–100). Default: 80. Values ≤ 1 are treated as fractions. */
75
75
  barWidth?: number;
76
76
  cornerRadius?: number;
77
77
  animationDuration?: number;
@@ -161,32 +161,8 @@ declare class AXBarChartComponent extends AXChartComponent implements OnDestroy,
161
161
  protected tooltipData: _angular_core.Signal<AXChartTooltipData>;
162
162
  private configToken;
163
163
  private chartColors;
164
- protected effectiveOptions: _angular_core.Signal<{
165
- width?: number;
166
- height?: number;
167
- showXAxis?: boolean;
168
- showYAxis?: boolean;
169
- showGrid?: boolean;
170
- showDataLabels?: boolean;
171
- xAxisLabel?: string;
172
- yAxisLabel?: string;
173
- rotateXAxisLabels?: boolean | "auto";
174
- showTooltip?: boolean;
175
- barWidth?: number;
176
- cornerRadius?: number;
177
- animationDuration?: number;
178
- animationDelay?: number;
179
- animationEasing?: _acorex_charts.AXAnimationEasing;
180
- messages?: _acorex_charts_bar_chart.AXBarChartMessages;
181
- }>;
182
- protected effectiveMessages: _angular_core.Signal<{
183
- noData: string;
184
- noDataHelp: string;
185
- allHidden: string;
186
- allHiddenHelp: string;
187
- noDataIcon: string;
188
- allHiddenIcon: string;
189
- }>;
164
+ protected effectiveOptions: _angular_core.Signal<AXBarChartOption>;
165
+ protected effectiveMessages: _angular_core.Signal<Required<_acorex_charts.AXChartMessages>>;
190
166
  private readonly hiddenBars;
191
167
  private readonly hiddenSeries;
192
168
  private readonly isClusteredMode;
@@ -319,7 +295,6 @@ declare class AXBarChartComponent extends AXChartComponent implements OnDestroy,
319
295
  */
320
296
  private getYAxisTickFontSizeBasedOnHeight;
321
297
  private buildXAxisCommon;
322
- private showMessage;
323
298
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXBarChartComponent, never>;
324
299
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXBarChartComponent, "ax-bar-chart", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, { "barClick": "barClick"; }, never, never, true, never>;
325
300
  }
@@ -1,4 +1,3 @@
1
- import * as _acorex_charts_donut_chart from '@acorex/charts/donut-chart';
2
1
  import * as _acorex_charts from '@acorex/charts';
3
2
  import { AXAnimationEasing, AXChartComponent, AXChartComponentBase } from '@acorex/charts';
4
3
  import * as d3 from 'd3';
@@ -156,18 +155,7 @@ declare class AXDonutChartComponent extends AXChartComponent implements OnDestro
156
155
  protected tooltipData: _angular_core.Signal<AXChartTooltipData>;
157
156
  private configToken;
158
157
  private chartColors;
159
- protected effectiveOptions: _angular_core.Signal<{
160
- width?: number;
161
- height?: number;
162
- totalLabel?: string;
163
- showTooltip?: boolean;
164
- showDataLabels?: boolean;
165
- donutWidth?: number;
166
- cornerRadius?: number;
167
- animationDuration?: number;
168
- animationEasing?: _acorex_charts.AXAnimationEasing;
169
- messages?: _acorex_charts_donut_chart.AXDonutChartMessages;
170
- }>;
158
+ protected effectiveOptions: _angular_core.Signal<AXDonutChartOption>;
171
159
  private readonly TOOLTIP_GAP;
172
160
  private readonly HIGHLIGHT_TRANSITION_DURATION;
173
161
  private readonly HIGHLIGHT_TRANSITION_NAME;
@@ -178,14 +166,9 @@ declare class AXDonutChartComponent extends AXChartComponent implements OnDestro
178
166
  private readonly CHART_INSET;
179
167
  private readonly DIMMED_OPACITY;
180
168
  private readonly VISIBLE_OPACITY;
181
- protected effectiveMessages: _angular_core.Signal<{
182
- noData: string;
183
- noDataHelp: string;
184
- allHidden: string;
185
- allHiddenHelp: string;
186
- noDataIcon: string;
187
- allHiddenIcon: string;
188
- }>;
169
+ private readonly instanceId;
170
+ private get segmentShadowFilterId();
171
+ protected effectiveMessages: _angular_core.Signal<Required<_acorex_charts.AXChartMessages>>;
189
172
  protected chartDataArray: _angular_core.Signal<AXDonutChartData[]>;
190
173
  protected getColor(index: number): string;
191
174
  protected isSegmentHidden(id: string): boolean;
@@ -299,7 +282,6 @@ declare class AXDonutChartComponent extends AXChartComponent implements OnDestro
299
282
  * Cleans up chart resources
300
283
  */
301
284
  cleanupChart(): void;
302
- private renderMessage;
303
285
  /**
304
286
  * Gets an accessibility label describing the donut chart for screen readers
305
287
  * @returns Descriptive string for screen readers
@@ -310,6 +292,10 @@ declare class AXDonutChartComponent extends AXChartComponent implements OnDestro
310
292
  * @implements AXChartLegendCompatible
311
293
  */
312
294
  getLegendItems(): AXChartLegendItem[];
295
+ private getSegmentLayoutValue;
296
+ private getLayoutTotal;
297
+ private getDisplayTotal;
298
+ private getSegmentPercentage;
313
299
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXDonutChartComponent, never>;
314
300
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXDonutChartComponent, "ax-donut-chart", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; }, { "segmentClick": "segmentClick"; "segmentHover": "segmentHover"; }, never, never, true, never>;
315
301
  }
@@ -1,4 +1,4 @@
1
- import { AXChartComponent, AX_CHART_COLOR_PALETTE, formatLargeNumber, getEasingFunction, getChartColor } from '@acorex/charts';
1
+ import { AX_CHART_DEFAULT_MESSAGES, AXChartComponent, AX_CHART_COLOR_PALETTE, mergeChartOptions, mergeChartMessages, resolveBarWidthFraction, formatLargeNumber, getEasingFunction, renderChartEmptyMessage, getChartColor } from '@acorex/charts';
2
2
  import { AXChartTooltipComponent } from '@acorex/charts/chart-tooltip';
3
3
  import * as i0 from '@angular/core';
4
4
  import { InjectionToken, input, output, viewChild, signal, inject, computed, afterNextRender, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
@@ -15,12 +15,8 @@ const AXBarChartDefaultConfig = {
15
15
  animationDuration: 800,
16
16
  animationEasing: 'cubic-out',
17
17
  messages: {
18
- noData: 'No data available',
19
- noDataHelp: 'Please provide data to display the chart',
20
- allHidden: 'All bars are hidden',
21
- allHiddenHelp: 'Click on legend items to show bars',
18
+ ...AX_CHART_DEFAULT_MESSAGES,
22
19
  noDataIcon: 'fa-light fa-chart-column',
23
- allHiddenIcon: 'fa-light fa-eye-slash',
24
20
  },
25
21
  };
26
22
  const AX_BAR_CHART_CONFIG = new InjectionToken('AX_BAR_CHART_CONFIG', {
@@ -28,11 +24,14 @@ const AX_BAR_CHART_CONFIG = new InjectionToken('AX_BAR_CHART_CONFIG', {
28
24
  factory: () => AXBarChartDefaultConfig,
29
25
  });
30
26
  function barChartConfig(config = {}) {
31
- const result = {
27
+ return {
32
28
  ...AXBarChartDefaultConfig,
33
29
  ...config,
30
+ messages: {
31
+ ...AXBarChartDefaultConfig.messages,
32
+ ...config.messages,
33
+ },
34
34
  };
35
- return result;
36
35
  }
37
36
 
38
37
  /**
@@ -42,9 +41,9 @@ function barChartConfig(config = {}) {
42
41
  class AXBarChartComponent extends AXChartComponent {
43
42
  // Inputs
44
43
  /** Chart data input */
45
- data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
44
+ data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
46
45
  /** Chart options input */
47
- options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
46
+ options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : []));
48
47
  // Outputs
49
48
  /** Emitted when a bar is clicked */
50
49
  barClick = output();
@@ -103,21 +102,21 @@ class AXBarChartComponent extends AXChartComponent {
103
102
  MANY_ITEMS_THRESHOLD = 20;
104
103
  VERY_MANY_ITEMS_THRESHOLD = 50;
105
104
  // Animation state
106
- _initialAnimationComplete = signal(false, ...(ngDevMode ? [{ debugName: "_initialAnimationComplete" }] : /* istanbul ignore next */ []));
105
+ _initialAnimationComplete = signal(false, ...(ngDevMode ? [{ debugName: "_initialAnimationComplete" }] : []));
107
106
  // Tooltip state
108
- _tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: "_tooltipVisible" }] : /* istanbul ignore next */ []));
109
- _tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : /* istanbul ignore next */ []));
107
+ _tooltipVisible = signal(false, ...(ngDevMode ? [{ debugName: "_tooltipVisible" }] : []));
108
+ _tooltipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : []));
110
109
  _tooltipData = signal({
111
110
  title: '',
112
111
  value: '0',
113
112
  percentage: '0%',
114
113
  color: '',
115
- }, ...(ngDevMode ? [{ debugName: "_tooltipData" }] : /* istanbul ignore next */ []));
114
+ }, ...(ngDevMode ? [{ debugName: "_tooltipData" }] : []));
116
115
  _tooltipRafId = null;
117
116
  _pendingTooltipCoords = null;
118
117
  // Signals for component state
119
- _initialized = signal(false, ...(ngDevMode ? [{ debugName: "_initialized" }] : /* istanbul ignore next */ []));
120
- _rendered = signal(false, ...(ngDevMode ? [{ debugName: "_rendered" }] : /* istanbul ignore next */ []));
118
+ _initialized = signal(false, ...(ngDevMode ? [{ debugName: "_initialized" }] : []));
119
+ _rendered = signal(false, ...(ngDevMode ? [{ debugName: "_rendered" }] : []));
121
120
  // Tooltip accessors
122
121
  tooltipVisible = this._tooltipVisible.asReadonly();
123
122
  tooltipPosition = this._tooltipPosition.asReadonly();
@@ -129,27 +128,9 @@ class AXBarChartComponent extends AXChartComponent {
129
128
  // Inject AXPlatform
130
129
  // Removed unused AXPlatform injection
131
130
  // Configuration with defaults
132
- effectiveOptions = computed(() => {
133
- return {
134
- ...this.configToken,
135
- ...this.options(),
136
- };
137
- }, ...(ngDevMode ? [{ debugName: "effectiveOptions" }] : /* istanbul ignore next */ []));
131
+ effectiveOptions = computed(() => mergeChartOptions(this.configToken, this.options()), ...(ngDevMode ? [{ debugName: "effectiveOptions" }] : []));
138
132
  // Messages with defaults
139
- effectiveMessages = computed(() => {
140
- const defaultMessages = {
141
- noData: 'No data available',
142
- noDataHelp: 'Please provide data to display the chart',
143
- allHidden: 'All bars are hidden',
144
- allHiddenHelp: 'Click on legend items to show bars',
145
- noDataIcon: 'fa-light fa-chart-column',
146
- allHiddenIcon: 'fa-light fa-eye-slash',
147
- };
148
- return {
149
- ...defaultMessages,
150
- ...this.effectiveOptions().messages,
151
- };
152
- }, ...(ngDevMode ? [{ debugName: "effectiveMessages" }] : /* istanbul ignore next */ []));
133
+ effectiveMessages = computed(() => mergeChartMessages(this.configToken.messages, this.options()?.messages), ...(ngDevMode ? [{ debugName: "effectiveMessages" }] : []));
153
134
  // Track hidden bars and series
154
135
  hiddenBars = new Set();
155
136
  hiddenSeries = new Set();
@@ -157,14 +138,14 @@ class AXBarChartComponent extends AXChartComponent {
157
138
  isClusteredMode = computed(() => {
158
139
  const value = this.data();
159
140
  return Array.isArray(value) && value.length > 0 && 'chartData' in value[0];
160
- }, ...(ngDevMode ? [{ debugName: "isClusteredMode" }] : /* istanbul ignore next */ []));
141
+ }, ...(ngDevMode ? [{ debugName: "isClusteredMode" }] : []));
161
142
  visibleData = computed(() => {
162
143
  const value = this.data() || [];
163
144
  if (this.isClusteredMode()) {
164
145
  return value;
165
146
  }
166
147
  return value.filter((d) => !this.hiddenBars.has(d.id));
167
- }, ...(ngDevMode ? [{ debugName: "visibleData" }] : /* istanbul ignore next */ []));
148
+ }, ...(ngDevMode ? [{ debugName: "visibleData" }] : []));
168
149
  hasVisibleData = computed(() => {
169
150
  const value = this.data();
170
151
  if (!Array.isArray(value) || value.length === 0)
@@ -173,10 +154,10 @@ class AXBarChartComponent extends AXChartComponent {
173
154
  const groups = value;
174
155
  const seriesLabels = this.getClusterSeriesLabels(groups);
175
156
  const visibleSeries = seriesLabels.filter((s) => !this.hiddenSeries.has(s));
176
- return groups.some((g) => visibleSeries.some((_, idx) => !!g.chartData[idx]));
157
+ return groups.some((g) => visibleSeries.some((label) => !!g.chartData.find((item) => item.label === label)));
177
158
  }
178
159
  return value.some((d) => !this.hiddenBars.has(d.id));
179
- }, ...(ngDevMode ? [{ debugName: "hasVisibleData" }] : /* istanbul ignore next */ []));
160
+ }, ...(ngDevMode ? [{ debugName: "hasVisibleData" }] : []));
180
161
  // Type guard helper
181
162
  isClusteredData(value) {
182
163
  return Array.isArray(value) && value.length > 0 && 'chartData' in value[0];
@@ -371,7 +352,7 @@ class AXBarChartComponent extends AXChartComponent {
371
352
  return Math.max(this.MIN_PLOT_HEIGHT, optionHeight - bottomPadding);
372
353
  }
373
354
  if (containerHeight > 0) {
374
- return Math.max(this.MIN_PLOT_HEIGHT, containerHeight - bottomPadding, this.FALLBACK_PLOT_HEIGHT);
355
+ return Math.max(this.MIN_PLOT_HEIGHT, containerHeight - bottomPadding);
375
356
  }
376
357
  return this.FALLBACK_PLOT_HEIGHT;
377
358
  }
@@ -389,10 +370,8 @@ class AXBarChartComponent extends AXChartComponent {
389
370
  * Creates x and y scales for the chart
390
371
  */
391
372
  setupScales(data) {
392
- // Get the bar width percentage (default 60%)
393
- const barWidthPercent = this.effectiveOptions().barWidth ?? 0.6;
394
- // Calculate padding based on barWidth (inverse relationship)
395
- const padding = Math.max(this.MIN_PADDING, 1 - barWidthPercent);
373
+ const barWidthFraction = resolveBarWidthFraction(this.effectiveOptions().barWidth);
374
+ const padding = Math.max(this.MIN_PADDING, 1 - barWidthFraction);
396
375
  // Create x scale (band scale for categorical data)
397
376
  this.xScale = this.d3
398
377
  .scaleBand()
@@ -430,8 +409,8 @@ class AXBarChartComponent extends AXChartComponent {
430
409
  // Y scale across all visible values (support negative values)
431
410
  const allVisibleValues = [];
432
411
  for (const g of groups) {
433
- visibleSeries.forEach((_, idx) => {
434
- const item = g.chartData[idx];
412
+ visibleSeries.forEach((label) => {
413
+ const item = g.chartData.find((d) => d.label === label);
435
414
  if (item && typeof item.value === 'number')
436
415
  allVisibleValues.push(item.value);
437
416
  });
@@ -572,8 +551,8 @@ class AXBarChartComponent extends AXChartComponent {
572
551
  const seriesLabels = groups.length > 0 ? this.getClusterSeriesLabels(groups) : [];
573
552
  const visibleSeries = seriesLabels.filter((s) => !this.hiddenSeries.has(s));
574
553
  for (const g of groups) {
575
- visibleSeries.forEach((_, idx) => {
576
- const item = g.chartData[idx];
554
+ visibleSeries.forEach((label) => {
555
+ const item = g.chartData.find((d) => d.label === label);
577
556
  if (item && typeof item.value === 'number')
578
557
  maxValue = Math.max(maxValue, item.value);
579
558
  });
@@ -789,7 +768,15 @@ class AXBarChartComponent extends AXChartComponent {
789
768
  .attr('transform', (g) => `translate(${this.xScale(g.id)},0)`);
790
769
  const barGroups = groupSel
791
770
  .selectAll('.ax-bar-chart-bar-group')
792
- .data((g) => visibleSeries.map((label, idx) => ({ group: g, seriesLabel: label, seriesIndex: idx })))
771
+ .data((g) => visibleSeries.map((label) => {
772
+ const seriesIndex = seriesLabels.indexOf(label);
773
+ return {
774
+ group: g,
775
+ seriesLabel: label,
776
+ seriesIndex,
777
+ item: g.chartData.find((d) => d.label === label) ?? g.chartData[seriesIndex],
778
+ };
779
+ }))
793
780
  .enter()
794
781
  .append('g')
795
782
  .style('cursor', 'pointer')
@@ -805,8 +792,7 @@ class AXBarChartComponent extends AXChartComponent {
805
792
  return `M${x},${y} L${x},${y} L${x + width},${y} L${x + width},${y} Z`;
806
793
  })
807
794
  .attr('fill', (d) => {
808
- const item = d.group.chartData[d.seriesIndex];
809
- return item?.color || this.getColor(d.seriesIndex);
795
+ return d.item?.color || this.getColor(d.seriesIndex);
810
796
  });
811
797
  if (this.effectiveOptions().showDataLabels !== false) {
812
798
  barGroups
@@ -820,10 +806,9 @@ class AXBarChartComponent extends AXChartComponent {
820
806
  .style('fill', 'rgb(var(--ax-comp-bar-chart-data-labels-color))')
821
807
  .style('opacity', 0)
822
808
  .text((d) => {
823
- const value = d.group.chartData[d.seriesIndex]?.value;
809
+ const value = d.item?.value;
824
810
  if (value === undefined)
825
811
  return '';
826
- // Format large numbers in data labels
827
812
  return value >= 1000 ? formatLargeNumber(value) : value;
828
813
  });
829
814
  const animationDelay = this.effectiveOptions().animationDelay ?? this.DEFAULT_ANIMATION_DELAY;
@@ -833,10 +818,9 @@ class AXBarChartComponent extends AXChartComponent {
833
818
  .duration(animationDuration)
834
819
  .delay((_d, i) => i * animationDelay + this.LABEL_ANIMATION_DELAY)
835
820
  .attr('y', (d) => {
836
- const item = d.group.chartData[d.seriesIndex];
837
- if (!item)
821
+ if (!d.item)
838
822
  return this.height;
839
- const barTop = this.yScale(item.value);
823
+ const barTop = this.yScale(d.item.value);
840
824
  // If bar is near the top (100% or close), position label inside the bar
841
825
  if (barTop < this.MIN_TOP_SPACE_FOR_LABEL) {
842
826
  return barTop + this.LABEL_OFFSET;
@@ -845,10 +829,9 @@ class AXBarChartComponent extends AXChartComponent {
845
829
  return barTop - this.LABEL_OFFSET;
846
830
  })
847
831
  .attr('data-inside-bar', (d) => {
848
- const item = d.group.chartData[d.seriesIndex];
849
- if (!item)
832
+ if (!d.item)
850
833
  return 'false';
851
- const barTop = this.yScale(item.value);
834
+ const barTop = this.yScale(d.item.value);
852
835
  return barTop < this.MIN_TOP_SPACE_FOR_LABEL ? 'true' : 'false';
853
836
  })
854
837
  .style('opacity', 1)
@@ -863,9 +846,8 @@ class AXBarChartComponent extends AXChartComponent {
863
846
  .transition()
864
847
  .duration(this.HOVER_TRANSITION_DURATION)
865
848
  .style('filter', 'brightness(0.7) drop-shadow(0 0 2px rgba(0,0,0,0.1))');
866
- const item = d.group.chartData[d.seriesIndex];
867
- if (item)
868
- this.handleBarHover(event, item, d.group);
849
+ if (d.item)
850
+ this.handleBarHover(event, d.item, d.group);
869
851
  })
870
852
  .on('mousemove', (event) => {
871
853
  if (this._initialAnimationComplete())
@@ -881,9 +863,8 @@ class AXBarChartComponent extends AXChartComponent {
881
863
  .on('click', (event, d) => {
882
864
  if (!this._initialAnimationComplete())
883
865
  return;
884
- const item = d.group.chartData[d.seriesIndex];
885
- if (item)
886
- this.handleBarClick(event, item);
866
+ if (d.item)
867
+ this.handleBarClick(event, d.item);
887
868
  });
888
869
  const animationDelay = this.effectiveOptions().animationDelay ?? this.DEFAULT_ANIMATION_DELAY;
889
870
  bars
@@ -893,8 +874,7 @@ class AXBarChartComponent extends AXChartComponent {
893
874
  .attrTween('d', (d) => {
894
875
  const x = this.xSubScale(d.seriesLabel);
895
876
  const width = this.xSubScale.bandwidth();
896
- const item = d.group.chartData[d.seriesIndex];
897
- const finalHeight = item ? this.height - this.yScale(item.value) : 0;
877
+ const finalHeight = d.item ? this.height - this.yScale(d.item.value) : 0;
898
878
  return (t) => {
899
879
  const currentHeight = finalHeight * t;
900
880
  const currentY = this.height - currentHeight;
@@ -1024,15 +1004,23 @@ class AXBarChartComponent extends AXChartComponent {
1024
1004
  * Shows a message when no data is available
1025
1005
  */
1026
1006
  showNoDataMessage(containerElement) {
1027
- this.clearChartArea(containerElement);
1028
- this.showMessage(containerElement, this.effectiveMessages().noDataIcon, this.effectiveMessages().noData, this.effectiveMessages().noDataHelp, 'ax-bar-chart-no-data-message');
1007
+ const messages = this.effectiveMessages();
1008
+ renderChartEmptyMessage(this.d3, containerElement, {
1009
+ icon: messages.noDataIcon,
1010
+ title: messages.noData,
1011
+ help: messages.noDataHelp,
1012
+ });
1029
1013
  }
1030
1014
  /**
1031
1015
  * Shows a message when all bars are hidden
1032
1016
  */
1033
1017
  showAllBarsHiddenMessage(containerElement) {
1034
- this.clearChartArea(containerElement);
1035
- this.showMessage(containerElement, this.effectiveMessages().allHiddenIcon, this.effectiveMessages().allHidden, this.effectiveMessages().allHiddenHelp, 'ax-bar-chart-no-data-message');
1018
+ const messages = this.effectiveMessages();
1019
+ renderChartEmptyMessage(this.d3, containerElement, {
1020
+ icon: messages.allHiddenIcon,
1021
+ title: messages.allHidden,
1022
+ help: messages.allHiddenHelp,
1023
+ });
1036
1024
  }
1037
1025
  /**
1038
1026
  * Gets the color for a bar based on its index
@@ -1237,7 +1225,7 @@ class AXBarChartComponent extends AXChartComponent {
1237
1225
  return this.chartContainerEl()?.nativeElement ?? null;
1238
1226
  }
1239
1227
  clearChartArea(containerElement) {
1240
- this.d3.select(containerElement).selectAll('svg, .ax-chart-message-container').remove();
1228
+ this.d3.select(containerElement).selectAll('svg, .ax-chart-empty, .ax-chart-message-container').remove();
1241
1229
  }
1242
1230
  /**
1243
1231
  * Truncates long labels with ellipsis
@@ -1325,26 +1313,13 @@ class AXBarChartComponent extends AXChartComponent {
1325
1313
  this.createXAxisTitle(axesGroup, options.xAxisLabel, tickAreaHeight, gapBelowTicks);
1326
1314
  }
1327
1315
  }
1328
- // computeTooltipPosition moved to shared chart utils
1329
- showMessage(containerElement, iconClass, text, helpText, specificClass) {
1330
- const container = this.d3
1331
- .select(containerElement)
1332
- .append('div')
1333
- .attr('class', `ax-chart-message-container ax-bar-chart-message-background ${specificClass}`);
1334
- container
1335
- .append('div')
1336
- .attr('class', 'ax-chart-message-icon ax-bar-chart-no-data-icon')
1337
- .html(`<i class="${iconClass} fa-2x"></i>`);
1338
- container.append('div').attr('class', 'ax-chart-message-text ax-bar-chart-no-data-text').text(text);
1339
- container.append('div').attr('class', 'ax-chart-message-help ax-bar-chart-no-data-help').text(helpText);
1340
- }
1341
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXBarChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1342
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: AXBarChartComponent, isStandalone: true, selector: "ax-bar-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { barClick: "barClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-bar-chart\" role=\"img\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["ax-bar-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);--ax-comp-bar-chart-axis-label-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-grid-lines-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-bg-color: 0, 0, 0, 0}ax-bar-chart .ax-bar-chart{width:100%;height:100%;position:relative;min-height:0;box-sizing:border-box;overflow:hidden;background-color:rgba(var(--ax-comp-bar-chart-bg-color))}ax-bar-chart .ax-bar-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%}ax-bar-chart .ax-bar-chart svg g:has(text){font-family:inherit}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label{pointer-events:none;-webkit-user-select:none;user-select:none}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label[data-inside-bar=true]{fill:#fff;font-weight:600;text-shadow:0 0 2px rgba(0,0,0,.3)}ax-bar-chart .ax-bar-chart-no-data-message{text-align:center;background-color:rgb(var(--ax-comp-bar-chart-bg-color));padding:1.5rem;border-radius:.5rem;border:1px solid rgba(var(--ax-sys-color-surface));width:80%;max-width:300px}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-icon{opacity:.6;margin-bottom:.75rem}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-text{font-size:1rem;font-weight:600;margin-bottom:.5rem}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-help{font-size:.8rem;opacity:.6}\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1316
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXBarChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1317
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.3", type: AXBarChartComponent, isStandalone: true, selector: "ax-bar-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { barClick: "barClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-bar-chart\" role=\"img\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [".ax-chart-empty{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;display:flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1rem;pointer-events:none}.ax-chart-empty__card{text-align:center;padding:1.5rem;border-radius:.5rem;border:1px solid rgba(var(--ax-sys-color-surface));width:80%;max-width:300px;box-sizing:border-box}.ax-chart-empty__icon{opacity:.6;margin-bottom:.75rem}.ax-chart-empty__title{font-size:1rem;font-weight:600;margin-bottom:.5rem}.ax-chart-empty__help{font-size:.8rem;opacity:.6}ax-bar-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);box-sizing:border-box;--ax-comp-bar-chart-axis-label-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-grid-lines-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-bg-color: 0, 0, 0, 0}ax-bar-chart .ax-bar-chart{width:100%;height:100%;position:relative;min-height:0;box-sizing:border-box;overflow:hidden;background-color:rgba(var(--ax-comp-bar-chart-bg-color))}ax-bar-chart .ax-bar-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%}ax-bar-chart .ax-bar-chart svg g:has(text){font-family:inherit}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label{pointer-events:none;-webkit-user-select:none;user-select:none}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label[data-inside-bar=true]{fill:#fff;font-weight:600;text-shadow:0 0 2px rgba(0,0,0,.3)}\n"], dependencies: [{ kind: "component", type: AXChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1343
1318
  }
1344
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXBarChartComponent, decorators: [{
1319
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.3", ngImport: i0, type: AXBarChartComponent, decorators: [{
1345
1320
  type: Component,
1346
- args: [{ selector: 'ax-bar-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-bar-chart\" role=\"img\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: ["ax-bar-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);--ax-comp-bar-chart-axis-label-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-grid-lines-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-bg-color: 0, 0, 0, 0}ax-bar-chart .ax-bar-chart{width:100%;height:100%;position:relative;min-height:0;box-sizing:border-box;overflow:hidden;background-color:rgba(var(--ax-comp-bar-chart-bg-color))}ax-bar-chart .ax-bar-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%}ax-bar-chart .ax-bar-chart svg g:has(text){font-family:inherit}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label{pointer-events:none;-webkit-user-select:none;user-select:none}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label[data-inside-bar=true]{fill:#fff;font-weight:600;text-shadow:0 0 2px rgba(0,0,0,.3)}ax-bar-chart .ax-bar-chart-no-data-message{text-align:center;background-color:rgb(var(--ax-comp-bar-chart-bg-color));padding:1.5rem;border-radius:.5rem;border:1px solid rgba(var(--ax-sys-color-surface));width:80%;max-width:300px}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-icon{opacity:.6;margin-bottom:.75rem}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-text{font-size:1rem;font-weight:600;margin-bottom:.5rem}ax-bar-chart .ax-bar-chart-no-data-message .ax-bar-chart-no-data-help{font-size:.8rem;opacity:.6}\n"] }]
1347
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], barClick: [{ type: i0.Output, args: ["barClick"] }], chartContainerEl: [{ type: i0.ViewChild, args: ['chartContainer', { isSignal: true }] }] } });
1321
+ args: [{ selector: 'ax-bar-chart', encapsulation: ViewEncapsulation.None, imports: [AXChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-bar-chart\" role=\"img\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [".ax-chart-empty{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;display:flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1rem;pointer-events:none}.ax-chart-empty__card{text-align:center;padding:1.5rem;border-radius:.5rem;border:1px solid rgba(var(--ax-sys-color-surface));width:80%;max-width:300px;box-sizing:border-box}.ax-chart-empty__icon{opacity:.6;margin-bottom:.75rem}.ax-chart-empty__title{font-size:1rem;font-weight:600;margin-bottom:.5rem}.ax-chart-empty__help{font-size:.8rem;opacity:.6}ax-bar-chart{display:block;width:100%;height:100%;min-height:clamp(220px,38vw,360px);box-sizing:border-box;--ax-comp-bar-chart-axis-label-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-data-labels-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-grid-lines-color: var(--ax-sys-color-on-lightest-surface);--ax-comp-bar-chart-bg-color: 0, 0, 0, 0}ax-bar-chart .ax-bar-chart{width:100%;height:100%;position:relative;min-height:0;box-sizing:border-box;overflow:hidden;background-color:rgba(var(--ax-comp-bar-chart-bg-color))}ax-bar-chart .ax-bar-chart svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%}ax-bar-chart .ax-bar-chart svg g:has(text){font-family:inherit}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label{pointer-events:none;-webkit-user-select:none;user-select:none}ax-bar-chart .ax-bar-chart .ax-bar-chart-data-label[data-inside-bar=true]{fill:#fff;font-weight:600;text-shadow:0 0 2px rgba(0,0,0,.3)}\n"] }]
1322
+ }], ctorParameters: () => [] });
1348
1323
 
1349
1324
  /**
1350
1325
  * Generated bundle index. Do not edit.