@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
@@ -1,7 +1,14 @@
1
1
  import { max, min, scaleBand, scaleLinear, scaleLog, scaleTime, } from 'd3';
2
- import { BaseChart } from './base-chart.js';
2
+ import { BaseChart, } from './base-chart.js';
3
3
  import { ChartValidator } from './validation.js';
4
4
  import { GROUPED_GAP_TICK_PREFIX, GROUPED_GROUP_LABEL_KEY, } from './grouped-data.js';
5
+ import { resolveScaleValue } from './scale-utils.js';
6
+ const DEFAULT_SERIES_COLOR = '#8884d8';
7
+ function isXYSeries(component) {
8
+ return (component.type === 'line' ||
9
+ component.type === 'bar' ||
10
+ component.type === 'area');
11
+ }
5
12
  export class XYChart extends BaseChart {
6
13
  constructor(config) {
7
14
  super(config);
@@ -35,95 +42,49 @@ export class XYChart extends BaseChart {
35
42
  writable: true,
36
43
  value: void 0
37
44
  });
45
+ Object.defineProperty(this, "orientation", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+ this.orientation = config.orientation ?? 'vertical';
38
52
  this.barStackMode = config.barStack?.mode ?? 'normal';
39
53
  this.barStackGap = config.barStack?.gap ?? 0.1;
40
54
  this.barStackReverseSeries = config.barStack?.reverseSeries ?? false;
41
55
  this.areaStackMode = config.areaStack?.mode ?? 'none';
42
56
  }
43
57
  addChild(component) {
44
- const type = component.type;
45
- if (type === 'line' || type === 'bar' || type === 'area') {
46
- const series = component;
47
- const defaultColor = '#8884d8';
48
- const colorIndex = this.series.length % this.theme.colorPalette.length;
49
- const newColor = this.theme.colorPalette[colorIndex];
50
- if (type === 'line') {
51
- const lineSeries = series;
52
- const currentColor = lineSeries.stroke;
53
- if (!currentColor || currentColor === defaultColor) {
54
- lineSeries.stroke = newColor;
55
- }
56
- }
57
- else if (type === 'bar') {
58
- const barSeries = series;
59
- const currentColor = barSeries.fill;
60
- if (!currentColor || currentColor === defaultColor) {
61
- barSeries.fill = newColor;
62
- }
63
- }
64
- else {
65
- const areaSeries = series;
66
- const isUsingDefaultColor = (!areaSeries.fill || areaSeries.fill === defaultColor) &&
67
- (!areaSeries.stroke || areaSeries.stroke === defaultColor);
68
- if (isUsingDefaultColor) {
69
- areaSeries.fill = newColor;
70
- areaSeries.stroke = newColor;
71
- }
72
- }
73
- this.series.push(series);
74
- }
75
- else if (type === 'xAxis') {
76
- this.xAxis = component;
58
+ if (isXYSeries(component)) {
59
+ this.series.push(this.resolveSeriesDefaults(component));
60
+ return this;
77
61
  }
78
- else if (type === 'yAxis') {
79
- this.yAxis = component;
80
- }
81
- else if (type === 'grid') {
82
- this.grid = component;
83
- }
84
- else if (type === 'tooltip') {
85
- this.tooltip = component;
86
- }
87
- else if (type === 'legend') {
88
- this.legend = component;
89
- this.legend.setToggleCallback(() => {
90
- this.rerender();
91
- });
92
- }
93
- else if (type === 'title') {
94
- this.title = component;
95
- }
96
- return this;
62
+ return super.addChild(component);
97
63
  }
98
64
  getExportComponents() {
99
- const components = [];
100
- if (this.title) {
101
- components.push(this.title);
102
- }
103
- if (this.grid) {
104
- components.push(this.grid);
105
- }
106
- components.push(...this.series);
107
- if (this.xAxis) {
108
- components.push(this.xAxis);
109
- }
110
- if (this.yAxis) {
111
- components.push(this.yAxis);
112
- }
113
- if (this.tooltip) {
114
- components.push(this.tooltip);
115
- }
116
- if (this.legend) {
117
- components.push(this.legend);
118
- }
119
- return components;
65
+ return [
66
+ ...this.getBaseExportComponents({
67
+ title: true,
68
+ grid: true,
69
+ }),
70
+ ...this.series,
71
+ ...this.getBaseExportComponents({
72
+ xAxis: true,
73
+ yAxis: true,
74
+ tooltip: true,
75
+ legend: true,
76
+ }),
77
+ ];
120
78
  }
121
79
  createExportChart() {
122
80
  return new XYChart({
123
81
  data: this.data,
82
+ width: this.configuredWidth,
83
+ height: this.configuredHeight,
124
84
  theme: this.theme,
125
85
  scales: this.scaleConfig,
126
86
  responsive: this.responsiveConfig,
87
+ orientation: this.orientation,
127
88
  barStack: {
128
89
  mode: this.barStackMode,
129
90
  gap: this.barStackGap,
@@ -136,34 +97,16 @@ export class XYChart extends BaseChart {
136
97
  }
137
98
  applyComponentOverrides(overrides) {
138
99
  const restoreBase = super.applyComponentOverrides(overrides);
139
- if (overrides.size === 0) {
140
- return restoreBase;
141
- }
142
- const previousSeries = [...this.series];
143
- this.series.forEach((series, index) => {
144
- const override = overrides.get(series);
145
- if (override &&
146
- (override.type === 'line' ||
147
- override.type === 'bar' ||
148
- override.type === 'area')) {
149
- this.series[index] = override;
150
- }
151
- });
100
+ const restoreSeries = this.applyArrayComponentOverrides(this.series, overrides, isXYSeries);
152
101
  return () => {
153
- this.series.splice(0, this.series.length, ...previousSeries);
102
+ restoreSeries();
154
103
  restoreBase();
155
104
  };
156
105
  }
157
- rerender() {
158
- if (!this.container) {
159
- return;
160
- }
161
- this.update(this.sourceData);
162
- }
163
- prepareLayout() {
164
- const svgNode = this.svg?.node();
106
+ prepareLayout(context) {
107
+ super.prepareLayout(context);
165
108
  this.xAxis?.clearEstimatedSpace?.();
166
- if (svgNode && this.xAxis) {
109
+ if (this.xAxis) {
167
110
  const xKey = this.getXKey();
168
111
  const labelKey = this.xAxis.labelKey;
169
112
  const labels = this.data.map((item) => {
@@ -172,16 +115,11 @@ export class XYChart extends BaseChart {
172
115
  }
173
116
  return item[xKey];
174
117
  });
175
- this.xAxis.estimateLayoutSpace?.(labels, this.theme, svgNode);
176
- }
177
- if (svgNode && this.legend?.isInlineMode()) {
178
- this.legend.estimateLayoutSpace(this.getLegendSeries(), this.theme, this.width, svgNode);
118
+ this.xAxis.estimateLayoutSpace?.(labels, this.renderTheme, context.svgNode);
179
119
  }
180
120
  }
181
- renderChart() {
182
- if (!this.plotArea) {
183
- throw new Error('Plot area not calculated');
184
- }
121
+ renderChart({ svg, plotGroup, plotArea, }) {
122
+ this.validateSeriesOrientation();
185
123
  this.series.forEach((series) => {
186
124
  const typeName = series.type === 'line'
187
125
  ? 'Line'
@@ -209,32 +147,26 @@ export class XYChart extends BaseChart {
209
147
  const categoryScaleType = this.getCategoryScaleType();
210
148
  const visibleSeries = this.getVisibleSeries();
211
149
  this.setupScales();
212
- if (this.title) {
213
- const titlePos = this.layoutManager.getComponentPosition(this.title);
214
- this.title.render(this.svg, this.theme, this.width, titlePos.x, titlePos.y);
215
- }
150
+ this.renderTitle(svg);
216
151
  if (this.grid && this.x && this.y) {
217
- this.grid.render(this.plotGroup, this.x, this.y, this.theme);
152
+ this.grid.render(plotGroup, this.x, this.y, this.renderTheme);
218
153
  }
219
154
  this.renderSeries(visibleSeries);
220
155
  if (this.x && this.y) {
221
156
  if (this.xAxis) {
222
- this.xAxis.render(this.svg, this.x, this.theme, this.plotArea.bottom, this.data);
157
+ this.xAxis.render(svg, this.x, this.renderTheme, plotArea.bottom, this.data);
223
158
  }
224
159
  if (this.yAxis) {
225
- this.yAxis.render(this.svg, this.y, this.theme, this.plotArea.left);
160
+ this.yAxis.render(svg, this.y, this.renderTheme, plotArea.left);
226
161
  }
227
162
  }
228
163
  if (this.tooltip && this.x && this.y) {
229
164
  const visibleAreaSeries = visibleSeries.filter((series) => series.type === 'area');
230
165
  const areaStackingContextBySeries = this.computeAreaStackingContexts(this.data, xKey, visibleAreaSeries);
231
- this.tooltip.initialize(this.theme);
232
- this.tooltip.attachToArea(this.svg, this.data, visibleSeries, xKey, this.x, this.y, this.theme, this.plotArea, this.parseValue.bind(this), this.isHorizontalOrientation(), categoryScaleType, (series, dataPoint) => this.getSeriesTooltipValue(series, dataPoint, xKey, areaStackingContextBySeries));
233
- }
234
- if (this.legend?.isInlineMode()) {
235
- const legendPos = this.layoutManager.getComponentPosition(this.legend);
236
- this.legend.render(this.svg, this.getLegendSeries(), this.theme, this.width, legendPos.x, legendPos.y);
166
+ this.tooltip.initialize(this.renderTheme);
167
+ this.tooltip.attachToArea(svg, this.data, visibleSeries, xKey, this.x, this.y, this.renderTheme, plotArea, this.parseValue.bind(this), this.isHorizontalOrientation(), categoryScaleType, (series, dataPoint) => this.getSeriesTooltipValue(series, dataPoint, xKey, areaStackingContextBySeries));
237
168
  }
169
+ this.renderInlineLegend(svg);
238
170
  }
239
171
  getXKey() {
240
172
  if (this.xAxis?.dataKey) {
@@ -261,11 +193,9 @@ export class XYChart extends BaseChart {
261
193
  return this.scaleConfig.x?.type || 'band';
262
194
  }
263
195
  getVisibleSeries() {
264
- const displaySeries = this.getDisplaySeries();
265
- if (!this.legend) {
266
- return displaySeries;
267
- }
268
- return displaySeries.filter((series) => this.legend.isSeriesVisible(series.dataKey));
196
+ return this.filterVisibleItems(this.getDisplaySeries(), (series) => {
197
+ return series.dataKey;
198
+ });
269
199
  }
270
200
  getDisplaySeries() {
271
201
  if (!this.barStackReverseSeries) {
@@ -288,9 +218,42 @@ export class XYChart extends BaseChart {
288
218
  return nextBar;
289
219
  });
290
220
  }
221
+ resolveSeriesDefaults(series) {
222
+ const colorIndex = this.series.length % this.theme.colorPalette.length;
223
+ const paletteColor = this.theme.colorPalette[colorIndex];
224
+ if (series.type === 'line') {
225
+ return this.cloneSeriesWithOverride(series, {
226
+ stroke: this.shouldReplaceSeriesColor(series.stroke)
227
+ ? paletteColor
228
+ : series.stroke,
229
+ });
230
+ }
231
+ if (series.type === 'bar') {
232
+ return this.cloneSeriesWithOverride(series, {
233
+ fill: this.shouldReplaceSeriesColor(series.fill)
234
+ ? paletteColor
235
+ : series.fill,
236
+ });
237
+ }
238
+ const shouldUsePaletteColor = this.shouldReplaceSeriesColor(series.fill) &&
239
+ this.shouldReplaceSeriesColor(series.stroke);
240
+ return this.cloneSeriesWithOverride(series, shouldUsePaletteColor
241
+ ? {
242
+ fill: paletteColor,
243
+ stroke: paletteColor,
244
+ }
245
+ : {});
246
+ }
247
+ shouldReplaceSeriesColor(color) {
248
+ return !color || color === DEFAULT_SERIES_COLOR;
249
+ }
250
+ cloneSeriesWithOverride(series, override) {
251
+ const exportable = series;
252
+ return exportable.createExportComponent(override);
253
+ }
291
254
  setupScales() {
292
255
  const xKey = this.getXKey();
293
- const isHorizontal = this.isHorizontalOrientation();
256
+ const isHorizontal = this.orientation === 'horizontal';
294
257
  let xConfig;
295
258
  let yConfig;
296
259
  if (isHorizontal) {
@@ -305,7 +268,21 @@ export class XYChart extends BaseChart {
305
268
  this.y = this.createScale(yConfig, isHorizontal ? xKey : null, 'y');
306
269
  }
307
270
  isHorizontalOrientation() {
308
- return this.series.some((s) => s.type === 'bar' && s.orientation === 'horizontal');
271
+ return this.orientation === 'horizontal';
272
+ }
273
+ validateSeriesOrientation() {
274
+ if (this.orientation !== 'horizontal') {
275
+ return;
276
+ }
277
+ const hasLineSeries = this.series.some((series) => {
278
+ return series.type === 'line';
279
+ });
280
+ const hasAreaSeries = this.series.some((series) => {
281
+ return series.type === 'area';
282
+ });
283
+ if (hasLineSeries || hasAreaSeries) {
284
+ throw new Error('XYChart: horizontal orientation currently supports Bar series only');
285
+ }
309
286
  }
310
287
  collectSeriesValues(series) {
311
288
  const values = [];
@@ -389,8 +366,8 @@ export class XYChart extends BaseChart {
389
366
  }
390
367
  else if (scaleType === 'time' && dataKey) {
391
368
  domain = [
392
- min(this.data, (d) => new Date(d[dataKey])),
393
- max(this.data, (d) => new Date(d[dataKey])),
369
+ min(this.data, (d) => resolveScaleValue(d[dataKey], 'time')),
370
+ max(this.data, (d) => resolveScaleValue(d[dataKey], 'time')),
394
371
  ];
395
372
  }
396
373
  else if ((scaleType === 'linear' || scaleType === 'log') && dataKey) {
@@ -555,13 +532,13 @@ export class XYChart extends BaseChart {
555
532
  gap: this.barStackGap,
556
533
  nextLayerData,
557
534
  };
558
- series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.theme, stackingContext);
535
+ series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.renderTheme, stackingContext, this.orientation);
559
536
  });
560
537
  areaSeries.forEach((series) => {
561
- series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.theme, areaStackingContextBySeries.get(series), areaValueLabelLayer ?? undefined);
538
+ series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.renderTheme, areaStackingContextBySeries.get(series), areaValueLabelLayer ?? undefined);
562
539
  });
563
540
  lineSeries.forEach((series) => {
564
- series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.theme);
541
+ series.render(this.plotGroup, this.data, xKey, this.x, this.y, this.parseValue, categoryScaleType, this.renderTheme);
565
542
  });
566
543
  if (areaValueLabelLayer) {
567
544
  areaValueLabelLayer.raise();
@@ -13,7 +13,7 @@ export declare class YAxis implements LayoutAwareComponent<YAxisConfigBase> {
13
13
  readonly exportHooks?: ExportHooks<YAxisConfigBase>;
14
14
  constructor(config?: YAxisConfig);
15
15
  getExportConfig(): YAxisConfigBase;
16
- createExportComponent(override?: Partial<YAxisConfigBase>): LayoutAwareComponent;
16
+ createExportComponent(override?: Partial<YAxisConfigBase>): LayoutAwareComponent<YAxisConfigBase>;
17
17
  /**
18
18
  * Returns the space required by the y-axis
19
19
  */
@@ -32,7 +32,6 @@ export class YAxis {
32
32
  writable: true,
33
33
  value: void 0
34
34
  });
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
35
  Object.defineProperty(this, "tickFormat", {
37
36
  enumerable: true,
38
37
  configurable: true,
@@ -108,11 +107,12 @@ export class YAxis {
108
107
  const axis = axisLeft(y).tickSize(0).tickPadding(this.tickPadding);
109
108
  // Apply tick formatting if specified
110
109
  if (this.tickFormat) {
111
- if (typeof this.tickFormat === 'function') {
112
- axis.ticks(5).tickFormat(this.tickFormat);
110
+ const tickFormat = this.tickFormat;
111
+ if (typeof tickFormat === 'function') {
112
+ axis.ticks(5).tickFormat((value) => tickFormat(value));
113
113
  }
114
114
  else {
115
- axis.ticks(5, this.tickFormat);
115
+ axis.ticks(5, tickFormat);
116
116
  }
117
117
  }
118
118
  else {
package/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
- "version": "0.8.0",
2
+ "version": "0.9.1",
3
3
  "name": "@internetstiftelsen/charts",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
7
7
  "./*": {
8
- "types": "./*.d.ts",
9
- "import": "./*.js"
10
- }
8
+ "types": "./dist/*.d.ts",
9
+ "import": "./dist/*.js"
10
+ },
11
+ "./package.json": "./package.json"
11
12
  },
12
13
  "files": [
13
- "*.js",
14
- "*.d.ts",
15
- "README.md"
14
+ "dist",
15
+ "README.md",
16
+ "LICENSE"
16
17
  ],
17
18
  "scripts": {
18
19
  "dev": "vite",
19
20
  "dev:docs": "vite --config vite.docs.config.ts --open",
20
- "build": "tsc --project tsconfig.lib.json && tsc-alias --project tsconfig.lib.json",
21
+ "build": "rm -rf dist && tsc --project tsconfig.lib.json && tsc-alias --project tsconfig.lib.json",
21
22
  "build:demo": "tsc -b && vite build",
22
23
  "build:docs": "vite build --config vite.docs.config.ts && cp -R docs dist-docs/docs",
23
24
  "lint": "eslint .",
@@ -26,55 +27,58 @@
26
27
  "preview:docs": "vite preview --config vite.docs.config.ts",
27
28
  "test": "vitest",
28
29
  "test:run": "vitest run",
30
+ "verify": "pnpm lint && pnpm test:run && pnpm build",
29
31
  "build:lib": "npm run build",
30
- "prepub": "rm -rf dist && npm run build:lib && cp package.json dist && cp README.md dist",
31
- "pub": "npm run prepub && cd dist && npm publish --access public"
32
+ "prepublishOnly": "pnpm verify",
33
+ "pub": "npm publish --access public"
32
34
  },
33
35
  "dependencies": {
34
- "@handsontable/react-wrapper": "^16.2.0",
35
- "@radix-ui/react-label": "^2.1.8",
36
- "@radix-ui/react-select": "^2.2.6",
37
- "@radix-ui/react-switch": "^1.2.6",
38
- "@radix-ui/react-tabs": "^1.1.13",
39
- "@types/d3": "^7.4.3",
40
- "class-variance-authority": "^0.7.1",
41
- "clsx": "^2.1.1",
42
36
  "d3": "^7.9.0",
43
- "handsontable": "^16.2.0",
44
- "lucide-react": "^0.548.0",
45
- "react": "^19.2.4",
46
- "react-dom": "^19.2.4",
47
- "tailwind-merge": "^3.4.0",
48
- "tailwindcss": "^4.1.18"
37
+ "d3-cloud": "^1.2.9"
49
38
  },
50
39
  "optionalDependencies": {
51
- "jspdf": "^4.1.0",
40
+ "jspdf": "^4.2.1",
52
41
  "xlsx": "^0.18.5"
53
42
  },
54
43
  "devDependencies": {
55
- "@eslint/js": "^9.39.2",
56
- "@internetstiftelsen/styleguide": "^5.1.23",
57
- "@speed-highlight/core": "^1.2.14",
58
- "@tailwindcss/vite": "^4.1.18",
44
+ "@eslint/js": "^9.39.4",
45
+ "@handsontable/react-wrapper": "^16.2.0",
46
+ "@internetstiftelsen/styleguide": "^5.1.24",
47
+ "@radix-ui/react-label": "^2.1.8",
48
+ "@radix-ui/react-select": "^2.2.6",
49
+ "@radix-ui/react-switch": "^1.2.6",
50
+ "@radix-ui/react-tabs": "^1.1.13",
51
+ "@speed-highlight/core": "^1.2.15",
52
+ "@tailwindcss/vite": "^4.2.2",
59
53
  "@testing-library/dom": "^10.4.1",
60
54
  "@testing-library/jest-dom": "^6.9.1",
61
55
  "@testing-library/react": "^16.3.2",
62
- "@types/node": "^24.10.13",
56
+ "@types/d3": "^7.4.3",
57
+ "@types/d3-cloud": "^1.2.9",
58
+ "@types/node": "^24.12.0",
63
59
  "@types/react": "^19.2.14",
64
60
  "@types/react-dom": "^19.2.3",
65
- "@vitejs/plugin-react-swc": "^4.2.3",
66
- "eslint": "^9.39.2",
61
+ "@vitejs/plugin-react-swc": "^4.3.0",
62
+ "class-variance-authority": "^0.7.1",
63
+ "clsx": "^2.1.1",
64
+ "eslint": "^9.39.4",
67
65
  "eslint-plugin-react-hooks": "^7.0.1",
68
66
  "eslint-plugin-react-refresh": "^0.4.26",
69
67
  "globals": "^16.5.0",
68
+ "handsontable": "^16.2.0",
70
69
  "jsdom": "^27.4.0",
70
+ "lucide-react": "^0.548.0",
71
71
  "prettier": "3.6.2",
72
- "sass": "^1.97.3",
72
+ "react": "^19.2.4",
73
+ "react-dom": "^19.2.4",
74
+ "sass": "^1.98.0",
75
+ "tailwind-merge": "^3.5.0",
76
+ "tailwindcss": "^4.2.2",
73
77
  "tsc-alias": "^1.8.16",
74
78
  "tw-animate-css": "^1.4.0",
75
79
  "typescript": "~5.9.3",
76
- "typescript-eslint": "^8.55.0",
80
+ "typescript-eslint": "^8.57.1",
77
81
  "vite": "^7.3.1",
78
- "vitest": "^4.0.18"
82
+ "vitest": "^4.1.0"
79
83
  }
80
84
  }
@@ -1,13 +0,0 @@
1
- import type { ExportHooks } from './types.js';
2
- export interface ChartComponent<TConfig = any> {
3
- type: 'line' | 'area' | 'bar' | 'xAxis' | 'yAxis' | 'grid' | 'tooltip' | 'legend' | 'title' | 'donutCenterContent';
4
- exportHooks?: ExportHooks<TConfig>;
5
- }
6
- export type ComponentSpace = {
7
- width: number;
8
- height: number;
9
- position: 'top' | 'bottom' | 'left' | 'right';
10
- };
11
- export interface LayoutAwareComponent<TConfig = any> extends ChartComponent<TConfig> {
12
- getRequiredSpace(): ComponentSpace;
13
- }
package/donut-chart.d.ts DELETED
@@ -1,38 +0,0 @@
1
- import type { DataItem, LegendSeries } from './types.js';
2
- import { BaseChart, type BaseChartConfig } from './base-chart.js';
3
- import type { ChartComponent, LayoutAwareComponent } from './chart-interface.js';
4
- export type DonutConfig = {
5
- innerRadius?: number;
6
- padAngle?: number;
7
- cornerRadius?: number;
8
- };
9
- export type DonutChartConfig = BaseChartConfig & {
10
- donut?: DonutConfig;
11
- valueKey?: string;
12
- labelKey?: string;
13
- };
14
- export declare class DonutChart extends BaseChart {
15
- private readonly innerRadiusRatio;
16
- private readonly padAngle;
17
- private readonly cornerRadius;
18
- private readonly valueKey;
19
- private readonly labelKey;
20
- private segments;
21
- private centerContent;
22
- constructor(config: DonutChartConfig);
23
- private validateDonutData;
24
- private prepareSegments;
25
- addChild(component: ChartComponent): this;
26
- protected getExportComponents(): ChartComponent[];
27
- update(data: DataItem[]): void;
28
- protected getLayoutComponents(): LayoutAwareComponent[];
29
- protected prepareLayout(): void;
30
- protected createExportChart(): BaseChart;
31
- protected applyComponentOverrides(overrides: Map<ChartComponent, ChartComponent>): () => void;
32
- protected renderChart(): void;
33
- private resolveFontScale;
34
- protected getLegendSeries(): LegendSeries[];
35
- private positionTooltip;
36
- private buildTooltipContent;
37
- private renderSegments;
38
- }