@internetstiftelsen/charts 0.8.0 → 0.9.1

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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -8
  3. package/{area.d.ts → dist/area.d.ts} +1 -2
  4. package/{area.js → dist/area.js} +2 -19
  5. package/{bar.d.ts → dist/bar.d.ts} +3 -5
  6. package/{bar.js → dist/bar.js} +8 -33
  7. package/{base-chart.d.ts → dist/base-chart.d.ts} +75 -14
  8. package/{base-chart.js → dist/base-chart.js} +429 -122
  9. package/dist/chart-interface.d.ts +19 -0
  10. package/{donut-center-content.d.ts → dist/donut-center-content.d.ts} +1 -1
  11. package/dist/donut-chart.d.ts +51 -0
  12. package/dist/donut-chart.js +374 -0
  13. package/{gauge-chart.d.ts → dist/gauge-chart.d.ts} +19 -8
  14. package/{gauge-chart.js → dist/gauge-chart.js} +317 -106
  15. package/{grid.d.ts → dist/grid.d.ts} +1 -1
  16. package/{layout-manager.d.ts → dist/layout-manager.d.ts} +5 -5
  17. package/{legend.d.ts → dist/legend.d.ts} +3 -1
  18. package/{legend.js → dist/legend.js} +32 -0
  19. package/{line.d.ts → dist/line.d.ts} +1 -1
  20. package/{line.js → dist/line.js} +3 -25
  21. package/{pie-chart.d.ts → dist/pie-chart.d.ts} +10 -21
  22. package/{pie-chart.js → dist/pie-chart.js} +51 -172
  23. package/dist/radial-chart-base.d.ts +25 -0
  24. package/dist/radial-chart-base.js +79 -0
  25. package/dist/scale-utils.d.ts +3 -0
  26. package/dist/scale-utils.js +14 -0
  27. package/{theme.d.ts → dist/theme.d.ts} +2 -0
  28. package/{theme.js → dist/theme.js} +24 -29
  29. package/{title.d.ts → dist/title.d.ts} +1 -1
  30. package/{tooltip.d.ts → dist/tooltip.d.ts} +1 -1
  31. package/{tooltip.js → dist/tooltip.js} +239 -74
  32. package/{types.d.ts → dist/types.d.ts} +27 -10
  33. package/{utils.d.ts → dist/utils.d.ts} +7 -2
  34. package/{utils.js → dist/utils.js} +24 -5
  35. package/dist/word-cloud-chart.d.ts +32 -0
  36. package/dist/word-cloud-chart.js +201 -0
  37. package/{x-axis.d.ts → dist/x-axis.d.ts} +2 -1
  38. package/{x-axis.js → dist/x-axis.js} +18 -14
  39. package/{xy-chart.d.ts → dist/xy-chart.d.ts} +14 -9
  40. package/{xy-chart.js → dist/xy-chart.js} +107 -130
  41. package/{y-axis.d.ts → dist/y-axis.d.ts} +1 -1
  42. package/{y-axis.js → dist/y-axis.js} +4 -4
  43. package/package.json +39 -35
  44. package/chart-interface.d.ts +0 -13
  45. package/donut-chart.d.ts +0 -38
  46. package/donut-chart.js +0 -316
  47. /package/{chart-interface.js → dist/chart-interface.js} +0 -0
  48. /package/{donut-center-content.js → dist/donut-center-content.js} +0 -0
  49. /package/{export-image.d.ts → dist/export-image.d.ts} +0 -0
  50. /package/{export-image.js → dist/export-image.js} +0 -0
  51. /package/{export-pdf.d.ts → dist/export-pdf.d.ts} +0 -0
  52. /package/{export-pdf.js → dist/export-pdf.js} +0 -0
  53. /package/{export-tabular.d.ts → dist/export-tabular.d.ts} +0 -0
  54. /package/{export-tabular.js → dist/export-tabular.js} +0 -0
  55. /package/{export-xlsx.d.ts → dist/export-xlsx.d.ts} +0 -0
  56. /package/{export-xlsx.js → dist/export-xlsx.js} +0 -0
  57. /package/{grid.js → dist/grid.js} +0 -0
  58. /package/{grouped-data.d.ts → dist/grouped-data.d.ts} +0 -0
  59. /package/{grouped-data.js → dist/grouped-data.js} +0 -0
  60. /package/{grouped-tabular.d.ts → dist/grouped-tabular.d.ts} +0 -0
  61. /package/{grouped-tabular.js → dist/grouped-tabular.js} +0 -0
  62. /package/{layout-manager.js → dist/layout-manager.js} +0 -0
  63. /package/{title.js → dist/title.js} +0 -0
  64. /package/{types.js → dist/types.js} +0 -0
  65. /package/{validation.d.ts → dist/validation.d.ts} +0 -0
  66. /package/{validation.js → dist/validation.js} +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Internetstiftelsen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -6,9 +6,12 @@ A framework-agnostic, composable charting library built on D3.js with TypeScript
6
6
 
7
7
  - **Framework Agnostic** - Works with vanilla JS, React, Vue, Svelte, or any framework
8
8
  - **Composable Architecture** - Build charts by composing components
9
- - **Multiple Chart Types** - XYChart (lines, areas, bars), DonutChart, PieChart, and GaugeChart
9
+ - **Multiple Chart Types** - XYChart (lines, areas, bars), WordCloudChart, DonutChart, PieChart, and GaugeChart
10
+ - **Radial Value Labels** - Pie and donut charts support optional on-chart labels with custom formatters
11
+ - **Optional Gauge Animation** - Animate gauge value transitions with `gauge.animate`
10
12
  - **Stacking Control** - Bar stacking modes with optional reversed visual series order
11
13
  - **Flexible Scales** - Band, linear, time, and logarithmic scales
14
+ - **Explicit or Responsive Sizing** - Set top-level `width`/`height` or let the container drive size
12
15
  - **Auto Resize** - Built-in ResizeObserver handles responsive behavior
13
16
  - **Responsive Policy** - Chart-level container-query overrides for theme and components
14
17
  - **Type Safe** - Written in TypeScript with full type definitions
@@ -81,6 +84,79 @@ chart
81
84
  chart.render('#chart-container');
82
85
  ```
83
86
 
87
+ Use top-level `width` and `height` for fixed-size charts, or omit them to size
88
+ from the render container.
89
+
90
+ Theme overrides are deep-partial, so nested overrides like
91
+ `theme.axis.fontSize` preserve the rest of the theme defaults.
92
+
93
+ Responsive overrides are declarative and merge all matching breakpoints in
94
+ declaration order:
95
+
96
+ ```typescript
97
+ const chart = new XYChart({
98
+ data,
99
+ responsive: {
100
+ breakpoints: {
101
+ sm: {
102
+ maxWidth: 640,
103
+ theme: {
104
+ axis: {
105
+ fontSize: 11,
106
+ },
107
+ },
108
+ components: [
109
+ {
110
+ match: { type: 'xAxis' },
111
+ override: { display: false },
112
+ },
113
+ ],
114
+ },
115
+ md: {
116
+ minWidth: 641,
117
+ maxWidth: 768,
118
+ theme: {
119
+ axis: {
120
+ fontSize: 12,
121
+ },
122
+ },
123
+ },
124
+ },
125
+ },
126
+ });
127
+ ```
128
+
129
+ ## Word Cloud
130
+
131
+ ```javascript
132
+ import { WordCloudChart } from '@internetstiftelsen/charts/word-cloud-chart';
133
+
134
+ const data = [
135
+ { word: 'internet', count: 96 },
136
+ { word: 'social', count: 82 },
137
+ { word: 'news', count: 75 },
138
+ ];
139
+
140
+ const chart = new WordCloudChart({
141
+ data,
142
+ wordCloud: {
143
+ minValue: 5,
144
+ minWordLength: 3,
145
+ minFontSize: 3,
146
+ maxFontSize: 20,
147
+ padding: 1,
148
+ spiral: 'archimedean',
149
+ },
150
+ });
151
+
152
+ chart.render('#word-cloud');
153
+ ```
154
+
155
+ `minFontSize` and `maxFontSize` are percentages of the smaller plot-area
156
+ dimension and define the relative size range passed into `d3-cloud`. The chart
157
+ expects flat `{ word, count }` rows, aggregates duplicate words after trimming,
158
+ and maps theme typography and colors directly into the layout and rendered SVG.
159
+
84
160
  ## Export
85
161
 
86
162
  `chart.export()` supports `svg`, `json`, `csv`, `xlsx`, `png`, `jpg`, and `pdf`.
@@ -104,12 +180,9 @@ It auto-detects grouped and normal (flat) table layouts.
104
180
  import { toChartData } from '@internetstiftelsen/charts/utils';
105
181
  import { XYChart } from '@internetstiftelsen/charts/xy-chart';
106
182
 
107
- const data = toChartData(
108
- '\t\tDaily\tWeekly\nAll users\tSegment A\t85%\t92%\n\tSegment B\t84%\t91%',
109
- {
110
- categoryKey: 'Category',
111
- },
112
- );
183
+ const data = toChartData('\t\tDaily\tWeekly\nAll users\tSegment A\t85%\t92%\n\tSegment B\t84%\t91%', {
184
+ categoryKey: 'Category',
185
+ });
113
186
 
114
187
  const chart = new XYChart({ data });
115
188
  chart.render('#chart-container');
@@ -118,16 +191,32 @@ chart.render('#chart-container');
118
191
  The parser supports JSON-escaped string payloads and grouped carry-forward row
119
192
  structure (blank first column on continuation rows).
120
193
 
194
+ Supported input shapes:
195
+
196
+ - Plain tab-delimited strings
197
+ - JSON-escaped string payloads
198
+
199
+ Auto-detection behavior:
200
+
201
+ - Grouped rows when a carry-forward group structure is present
202
+ - Flat rows when no grouped continuation rows are detected
203
+
204
+ Grouped parsing rules:
205
+
206
+ - Header row starts with two structural columns (`group`, `category`) before metrics
207
+ - Continuation rows leave the first column blank to inherit the previous group
208
+ - Blank separator rows are ignored
209
+
121
210
  ## Documentation
122
211
 
123
212
  - [Getting Started](./docs/getting-started.md) - Installation, Vanilla JS, React integration
124
213
  - [XYChart](./docs/xy-chart.md) - Line, area, and bar charts API
214
+ - [WordCloudChart](./docs/word-cloud-chart.md) - Word frequency visualization API
125
215
  - [DonutChart](./docs/donut-chart.md) - Donut/pie charts API
126
216
  - [PieChart](./docs/pie-chart.md) - Pie chart API
127
217
  - [GaugeChart](./docs/gauge-chart.md) - Gauge chart API
128
218
  - [Components](./docs/components.md) - Axes, Grid, Tooltip, Legend, Title
129
219
  - [Theming](./docs/theming.md) - Colors, fonts, and styling
130
- - [Advanced](./docs/advanced.md) - Scales, TypeScript, architecture, performance
131
220
 
132
221
  ## Browser Support
133
222
 
@@ -18,8 +18,7 @@ export declare class Area implements ChartComponent<AreaConfigBase> {
18
18
  readonly exportHooks?: ExportHooks<AreaConfigBase>;
19
19
  constructor(config: AreaConfig);
20
20
  getExportConfig(): AreaConfigBase;
21
- createExportComponent(override?: Partial<AreaConfigBase>): ChartComponent;
22
- private getScaledPosition;
21
+ createExportComponent(override?: Partial<AreaConfigBase>): ChartComponent<AreaConfigBase>;
23
22
  private getStackValues;
24
23
  render(plotGroup: Selection<SVGGElement, undefined, null, undefined>, data: DataItem[], xKey: string, x: D3Scale, y: D3Scale, parseValue: (value: unknown) => number, xScaleType: ScaleType | undefined, theme: ChartTheme, stackingContext?: AreaStackingContext, valueLabelLayer?: Selection<SVGGElement, undefined, null, undefined>): void;
25
24
  private renderValueLabels;
@@ -1,5 +1,6 @@
1
1
  import { area, curveBasis, curveCardinal, curveLinear, curveMonotoneX, curveNatural, curveStep, line, } from 'd3';
2
2
  import { mergeDeep, sanitizeForCSS } from './utils.js';
3
+ import { getScalePosition } from './scale-utils.js';
3
4
  const AREA_CURVE_FACTORIES = {
4
5
  linear: curveLinear,
5
6
  monotone: curveMonotoneX,
@@ -132,24 +133,6 @@ export class Area {
132
133
  exportHooks: this.exportHooks,
133
134
  });
134
135
  }
135
- getScaledPosition(data, key, scale, scaleType) {
136
- const value = data[key];
137
- let scaledValue;
138
- switch (scaleType) {
139
- case 'band':
140
- scaledValue = String(value);
141
- break;
142
- case 'time':
143
- scaledValue =
144
- value instanceof Date ? value : new Date(String(value));
145
- break;
146
- case 'linear':
147
- case 'log':
148
- scaledValue = typeof value === 'number' ? value : Number(value);
149
- break;
150
- }
151
- return scale(scaledValue) || 0;
152
- }
153
136
  getStackValues(dataPoint, xKey, parseValue, stackingContext) {
154
137
  const value = parseValue(dataPoint[this.dataKey]);
155
138
  if (!stackingContext || stackingContext.mode === 'none') {
@@ -176,7 +159,7 @@ export class Area {
176
159
  }
177
160
  render(plotGroup, data, xKey, x, y, parseValue, xScaleType = 'band', theme, stackingContext, valueLabelLayer) {
178
161
  const getXPosition = (d) => {
179
- const scaled = this.getScaledPosition(d.data, xKey, x, xScaleType);
162
+ const scaled = getScalePosition(x, d.data[xKey], xScaleType);
180
163
  return scaled + (x.bandwidth ? x.bandwidth() / 2 : 0);
181
164
  };
182
165
  const hasValidValue = (d) => {
@@ -1,20 +1,18 @@
1
1
  import type { Selection } from 'd3';
2
- import type { BarConfig, BarStackingContext, BarValueLabelConfig, ChartTheme, D3Scale, DataItem, Orientation, ScaleType, ExportHooks, BarConfigBase } from './types.js';
2
+ import type { BarConfig, BarStackingContext, BarValueLabelConfig, ChartTheme, D3Scale, DataItem, ScaleType, ExportHooks, BarConfigBase } from './types.js';
3
3
  import type { ChartComponent } from './chart-interface.js';
4
4
  export declare class Bar implements ChartComponent<BarConfigBase> {
5
5
  readonly type: "bar";
6
6
  readonly dataKey: string;
7
7
  readonly fill: string;
8
8
  readonly colorAdapter?: (data: DataItem, index: number) => string;
9
- readonly orientation: Orientation;
10
9
  readonly maxBarSize?: number;
11
10
  readonly valueLabel?: BarValueLabelConfig;
12
11
  readonly exportHooks?: ExportHooks<BarConfigBase>;
13
12
  constructor(config: BarConfig);
14
13
  getExportConfig(): BarConfigBase;
15
- createExportComponent(override?: Partial<BarConfigBase>): ChartComponent;
16
- private getScaledPosition;
17
- render(plotGroup: Selection<SVGGElement, undefined, null, undefined>, data: DataItem[], xKey: string, x: D3Scale, y: D3Scale, parseValue: (value: unknown) => number, xScaleType?: ScaleType, theme?: ChartTheme, stackingContext?: BarStackingContext): void;
14
+ createExportComponent(override?: Partial<BarConfigBase>): ChartComponent<BarConfigBase>;
15
+ render(plotGroup: Selection<SVGGElement, undefined, null, undefined>, data: DataItem[], xKey: string, x: D3Scale, y: D3Scale, parseValue: (value: unknown) => number, xScaleType?: ScaleType, theme?: ChartTheme, stackingContext?: BarStackingContext, orientation?: 'vertical' | 'horizontal'): void;
18
16
  private renderVertical;
19
17
  private renderHorizontal;
20
18
  private renderVerticalValueLabels;
@@ -1,4 +1,5 @@
1
1
  import { getContrastTextColor, sanitizeForCSS, mergeDeep } from './utils.js';
2
+ import { getScalePosition } from './scale-utils.js';
2
3
  const LABEL_INSET_DEFAULT = 4;
3
4
  const LABEL_INSET_STACKED = 6;
4
5
  const LABEL_MIN_PADDING_DEFAULT = 8;
@@ -39,12 +40,6 @@ export class Bar {
39
40
  writable: true,
40
41
  value: void 0
41
42
  });
42
- Object.defineProperty(this, "orientation", {
43
- enumerable: true,
44
- configurable: true,
45
- writable: true,
46
- value: void 0
47
- });
48
43
  Object.defineProperty(this, "maxBarSize", {
49
44
  enumerable: true,
50
45
  configurable: true,
@@ -66,7 +61,6 @@ export class Bar {
66
61
  this.dataKey = config.dataKey;
67
62
  this.fill = config.fill || '#8884d8';
68
63
  this.colorAdapter = config.colorAdapter;
69
- this.orientation = config.orientation || 'vertical';
70
64
  this.maxBarSize = config.maxBarSize;
71
65
  this.valueLabel = config.valueLabel;
72
66
  this.exportHooks = config.exportHooks;
@@ -76,7 +70,6 @@ export class Bar {
76
70
  dataKey: this.dataKey,
77
71
  fill: this.fill,
78
72
  colorAdapter: this.colorAdapter,
79
- orientation: this.orientation,
80
73
  maxBarSize: this.maxBarSize,
81
74
  valueLabel: this.valueLabel,
82
75
  };
@@ -88,26 +81,8 @@ export class Bar {
88
81
  exportHooks: this.exportHooks,
89
82
  });
90
83
  }
91
- getScaledPosition(data, key, scale, scaleType) {
92
- const value = data[key];
93
- let scaledValue;
94
- switch (scaleType) {
95
- case 'band':
96
- scaledValue = String(value);
97
- break;
98
- case 'time':
99
- scaledValue =
100
- value instanceof Date ? value : new Date(String(value));
101
- break;
102
- case 'linear':
103
- case 'log':
104
- scaledValue = typeof value === 'number' ? value : Number(value);
105
- break;
106
- }
107
- return scale(scaledValue) || 0;
108
- }
109
- render(plotGroup, data, xKey, x, y, parseValue, xScaleType = 'band', theme, stackingContext) {
110
- if (this.orientation === 'vertical') {
84
+ render(plotGroup, data, xKey, x, y, parseValue, xScaleType = 'band', theme, stackingContext, orientation = 'vertical') {
85
+ if (orientation === 'vertical') {
111
86
  this.renderVertical(plotGroup, data, xKey, x, y, parseValue, xScaleType, stackingContext);
112
87
  }
113
88
  else {
@@ -115,7 +90,7 @@ export class Bar {
115
90
  }
116
91
  // Render value labels if enabled
117
92
  if (this.valueLabel?.show && theme) {
118
- if (this.orientation === 'vertical') {
93
+ if (orientation === 'vertical') {
119
94
  this.renderVerticalValueLabels(plotGroup, data, xKey, x, y, parseValue, xScaleType, theme, stackingContext);
120
95
  }
121
96
  else {
@@ -178,7 +153,7 @@ export class Bar {
178
153
  .attr('class', `bar-${sanitizedKey}`)
179
154
  .attr('data-index', (_, i) => i)
180
155
  .attr('x', (d) => {
181
- const xPos = this.getScaledPosition(d, xKey, x, xScaleType);
156
+ const xPos = getScalePosition(x, d[xKey], xScaleType);
182
157
  return xScaleType === 'band'
183
158
  ? xPos + barOffset
184
159
  : xPos - barWidth / 2;
@@ -301,7 +276,7 @@ export class Bar {
301
276
  }
302
277
  })
303
278
  .attr('y', (d) => {
304
- const yPos = this.getScaledPosition(d, xKey, y, yScaleType);
279
+ const yPos = getScalePosition(y, d[xKey], yScaleType);
305
280
  return yScaleType === 'band'
306
281
  ? yPos + barOffset
307
282
  : yPos - barHeight / 2;
@@ -388,7 +363,7 @@ export class Bar {
388
363
  const categoryKey = String(d[xKey]);
389
364
  const value = parseValue(d[this.dataKey]);
390
365
  const valueText = String(value);
391
- const xPos = this.getScaledPosition(d, xKey, x, xScaleType);
366
+ const xPos = getScalePosition(x, d[xKey], xScaleType);
392
367
  const barColor = this.colorAdapter
393
368
  ? this.colorAdapter(d, i)
394
369
  : this.fill;
@@ -572,7 +547,7 @@ export class Bar {
572
547
  const categoryKey = String(d[xKey]);
573
548
  const value = parseValue(d[this.dataKey]);
574
549
  const valueText = String(value);
575
- const yPos = this.getScaledPosition(d, xKey, y, yScaleType);
550
+ const yPos = getScalePosition(y, d[xKey], yScaleType);
576
551
  const barColor = this.colorAdapter
577
552
  ? this.colorAdapter(d, i)
578
553
  : this.fill;
@@ -1,6 +1,6 @@
1
1
  import { type Selection } from 'd3';
2
- import type { ChartData, DataItem, ChartTheme, AxisScaleConfig, ExportFormat, ExportOptions, D3Scale, ExportHookContext, ExportRenderContext, LegendItem, LegendSeries, ResponsiveConfig, ResponsiveRenderContext, DeepPartial } from './types.js';
3
- import type { ChartComponent, LayoutAwareComponent } from './chart-interface.js';
2
+ import type { ChartData, DataItem, ChartTheme, ResolvedChartTheme, AxisScaleConfig, ExportFormat, ExportOptions, D3Scale, ExportHookContext, ExportRenderContext, LegendItem, LegendSeries, ResponsiveConfig, ResponsiveRenderContext, DeepPartial } from './types.js';
3
+ import type { ChartComponentBase, LayoutAwareComponentBase } from './chart-interface.js';
4
4
  import type { XAxis } from './x-axis.js';
5
5
  import type { YAxis } from './y-axis.js';
6
6
  import type { Grid } from './grid.js';
@@ -12,15 +12,46 @@ type VisualExportFormat = 'svg' | 'png' | 'jpg' | 'pdf';
12
12
  type RenderDimensions = {
13
13
  width: number;
14
14
  height: number;
15
+ svgWidthAttr: number | string;
15
16
  svgHeightAttr: number | string;
16
17
  };
17
18
  type ResponsiveOverrides = {
18
19
  theme?: DeepPartial<ChartTheme>;
19
- components: Map<ChartComponent, Record<string, unknown>>;
20
+ components: Map<ChartComponentBase, Record<string, unknown>>;
21
+ };
22
+ type BaseLayoutComponentsOptions = {
23
+ title?: boolean;
24
+ xAxis?: boolean;
25
+ yAxis?: boolean;
26
+ inlineLegend?: boolean;
27
+ };
28
+ type BaseExportComponentsOptions = {
29
+ title?: boolean;
30
+ grid?: boolean;
31
+ xAxis?: boolean;
32
+ yAxis?: boolean;
33
+ tooltip?: boolean;
34
+ legend?: boolean;
35
+ };
36
+ export type BaseLayoutContext = {
37
+ svg: Selection<SVGSVGElement, undefined, null, undefined>;
38
+ svgNode: SVGSVGElement;
39
+ };
40
+ export type BaseRenderContext = BaseLayoutContext & {
41
+ plotGroup: Selection<SVGGElement, undefined, null, undefined>;
42
+ plotArea: PlotAreaBounds;
43
+ };
44
+ type ComponentSlot<TComponent extends ChartComponentBase = ChartComponentBase> = {
45
+ type: TComponent['type'];
46
+ get: () => TComponent | null;
47
+ set: (component: TComponent | null) => void;
48
+ onRegister?: (component: TComponent) => void;
20
49
  };
21
50
  export type BaseChartConfig = {
22
51
  data: ChartData;
23
- theme?: Partial<ChartTheme>;
52
+ width?: number;
53
+ height?: number;
54
+ theme?: DeepPartial<ChartTheme>;
24
55
  scales?: AxisScaleConfig;
25
56
  responsive?: ResponsiveConfig;
26
57
  };
@@ -30,6 +61,8 @@ export type BaseChartConfig = {
30
61
  export declare abstract class BaseChart {
31
62
  protected data: DataItem[];
32
63
  protected sourceData: ChartData;
64
+ protected readonly configuredWidth?: number;
65
+ protected readonly configuredHeight?: number;
33
66
  protected readonly theme: ChartTheme;
34
67
  protected readonly scaleConfig: AxisScaleConfig;
35
68
  protected readonly responsiveConfig?: ResponsiveConfig;
@@ -49,12 +82,15 @@ export declare abstract class BaseChart {
49
82
  protected resizeObserver: ResizeObserver | null;
50
83
  protected layoutManager: LayoutManager;
51
84
  protected plotArea: PlotAreaBounds | null;
85
+ private readyPromise;
52
86
  private disconnectedLegendContainer;
87
+ private renderThemeOverride;
88
+ private renderSizeOverride;
53
89
  protected constructor(config: BaseChartConfig);
54
90
  /**
55
91
  * Adds a component (axis, grid, tooltip, etc.) to the chart
56
92
  */
57
- abstract addChild(component: ChartComponent): this;
93
+ addChild(component: ChartComponentBase): this;
58
94
  /**
59
95
  * Renders the chart to the specified target element
60
96
  */
@@ -65,27 +101,45 @@ export declare abstract class BaseChart {
65
101
  */
66
102
  private performRender;
67
103
  protected resolveRenderDimensions(containerRect: DOMRect): RenderDimensions;
104
+ private resolveAccessibleLabel;
105
+ private syncAccessibleLabelFromSvg;
68
106
  protected resolveResponsiveContext(context: {
69
107
  width: number;
70
108
  height: number;
71
109
  }): ResponsiveRenderContext;
72
- private resolveBreakpointName;
110
+ private resolveActiveBreakpoints;
73
111
  private resolveRenderTheme;
74
- private applyThemeOverride;
112
+ private applyRenderTheme;
113
+ protected get renderTheme(): ChartTheme;
114
+ protected get resolvedRenderTheme(): ResolvedChartTheme;
75
115
  /**
76
116
  * Get layout-aware components in order
77
117
  * Override in subclasses to provide chart-specific components
78
118
  */
79
- protected getLayoutComponents(): LayoutAwareComponent[];
80
- protected getExportComponents(): ChartComponent[];
81
- protected collectExportOverrides(context: ExportRenderContext): Map<ChartComponent, Record<string, unknown>>;
119
+ protected getLayoutComponents(): LayoutAwareComponentBase[];
120
+ protected getBaseLayoutComponents(options: BaseLayoutComponentsOptions): LayoutAwareComponentBase[];
121
+ protected getExportComponents(): ChartComponentBase[];
122
+ protected getOverrideableComponents(): ChartComponentBase[];
123
+ protected getBaseExportComponents(options: BaseExportComponentsOptions): ChartComponentBase[];
124
+ protected registerBaseComponent(component: ChartComponentBase): boolean;
125
+ protected collectExportOverrides(context: ExportRenderContext): Map<ChartComponentBase, Record<string, unknown>>;
82
126
  protected collectResponsiveOverrides(context: ResponsiveRenderContext): ResponsiveOverrides;
127
+ private collectResponsiveBreakpointOverrides;
128
+ private createResponsiveComponentSnapshots;
129
+ private applyResponsiveComponentOverrideEntries;
83
130
  protected runExportHooks(context: ExportHookContext): void;
84
131
  private mergeComponentOverrideMaps;
85
132
  private createOverrideComponents;
86
- protected applyComponentOverrides(overrides: Map<ChartComponent, ChartComponent>): () => void;
133
+ protected applyComponentOverrides(overrides: Map<ChartComponentBase, ChartComponentBase>): () => void;
87
134
  private renderExportChart;
88
- protected prepareLayout(): void;
135
+ protected renderTitle(svg: Selection<SVGSVGElement, undefined, null, undefined>): void;
136
+ protected renderInlineLegend(svg: Selection<SVGSVGElement, undefined, null, undefined>): void;
137
+ protected measureInlineLegend(svgNode: SVGSVGElement): void;
138
+ protected filterVisibleItems<T>(items: T[], getDataKey: (item: T) => string): T[];
139
+ protected validateSourceData(_data: ChartData): void;
140
+ protected syncDerivedState(_previousData?: DataItem[]): void;
141
+ protected initializeDataState(): void;
142
+ protected prepareLayout(context: BaseLayoutContext): void;
89
143
  /**
90
144
  * Setup ResizeObserver for automatic resize handling
91
145
  */
@@ -93,8 +147,10 @@ export declare abstract class BaseChart {
93
147
  /**
94
148
  * Subclasses must implement this method to define their rendering logic
95
149
  */
96
- protected abstract renderChart(): void;
150
+ protected abstract renderChart(context: BaseRenderContext): void;
97
151
  protected abstract createExportChart(): BaseChart;
152
+ protected setReadyPromise(promise: Promise<void>): void;
153
+ whenReady(): Promise<void>;
98
154
  protected getLegendSeries(): LegendSeries[];
99
155
  getLegendItems(): LegendItem[];
100
156
  isLegendSeriesVisible(dataKey: string): boolean;
@@ -114,6 +170,11 @@ export declare abstract class BaseChart {
114
170
  private resolveDisconnectedLegendHost;
115
171
  private cleanupDisconnectedLegendContainer;
116
172
  protected parseValue(value: unknown): number;
173
+ protected rerender(): void;
174
+ protected tryRegisterComponent(component: ChartComponentBase, slots: readonly ComponentSlot[]): boolean;
175
+ protected applySlotOverrides(overrides: Map<ChartComponentBase, ChartComponentBase>, slots: readonly ComponentSlot[]): () => void;
176
+ protected applyArrayComponentOverrides<TComponent extends ChartComponentBase>(components: TComponent[], overrides: Map<ChartComponentBase, ChartComponentBase>, isComponent: (component: ChartComponentBase) => component is TComponent): () => void;
177
+ private getBaseComponentSlots;
117
178
  /**
118
179
  * Exports the chart in the specified format
119
180
  * @param format - The export format
@@ -131,7 +192,7 @@ export declare abstract class BaseChart {
131
192
  private exportXLSX;
132
193
  private exportImage;
133
194
  private exportPDF;
134
- protected exportSVG(options?: ExportOptions, formatForHooks?: VisualExportFormat): string;
195
+ protected exportSVG(options?: ExportOptions, formatForHooks?: VisualExportFormat): Promise<string>;
135
196
  protected exportJSON(): string;
136
197
  }
137
198
  export {};