@internetstiftelsen/charts 0.9.1 → 0.10.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.
package/README.md CHANGED
@@ -6,11 +6,15 @@ 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), WordCloudChart, DonutChart, PieChart, and GaugeChart
9
+ - **Multiple Chart Types** - XYChart (lines, scatter, areas, bars), WordCloudChart, DonutChart, PieChart, and GaugeChart
10
+ - **Combined Chart Layouts** - `ChartGroup` composes existing charts into shared dashboards with one coordinated legend
11
+ - **Divergent Bar Support** - Bar charts automatically render from zero and diverge around `0` for mixed positive/negative values
12
+ - **Mirrored Bar Sides** - Horizontal bars can mirror a series to the left for population-pyramid style charts without changing source data
10
13
  - **Radial Value Labels** - Pie and donut charts support optional on-chart labels with custom formatters
11
14
  - **Optional Gauge Animation** - Animate gauge value transitions with `gauge.animate`
12
15
  - **Stacking Control** - Bar stacking modes with optional reversed visual series order
13
- - **Flexible Scales** - Band, linear, time, and logarithmic scales
16
+ - **Axis Direction Control** - Use `scales.x.reverse` / `scales.y.reverse` to flip an axis when needed
17
+ - **Flexible Scales** - Band, linear, time, and logarithmic scales (bar value axes stay linear)
14
18
  - **Explicit or Responsive Sizing** - Set top-level `width`/`height` or let the container drive size
15
19
  - **Auto Resize** - Built-in ResizeObserver handles responsive behavior
16
20
  - **Responsive Policy** - Chart-level container-query overrides for theme and components
@@ -24,6 +28,22 @@ A framework-agnostic, composable charting library built on D3.js with TypeScript
24
28
  npm install @internetstiftelsen/charts
25
29
  ```
26
30
 
31
+ ## Agent Skill
32
+
33
+ This repo also ships a Codex-compatible skill in
34
+ `skills/build-internetstiftelsen-charts`.
35
+
36
+ Install it globally for Codex with `skills.sh`:
37
+
38
+ ```bash
39
+ npx skills add git@gitlab.com:internetstiftelsen/internal/webbgruppen/packages/charts.git \
40
+ -a codex \
41
+ -g \
42
+ --skill build-internetstiftelsen-charts
43
+ ```
44
+
45
+ Restart Codex after installation so the new skill is discovered.
46
+
27
47
  ## Local Development
28
48
 
29
49
  ```bash
@@ -90,6 +110,119 @@ from the render container.
90
110
  Theme overrides are deep-partial, so nested overrides like
91
111
  `theme.axis.fontSize` preserve the rest of the theme defaults.
92
112
 
113
+ ## Chart Groups
114
+
115
+ Use `ChartGroup` when you want to combine existing charts into one layout while
116
+ keeping each child chart fully functional.
117
+
118
+ ```javascript
119
+ import { ChartGroup } from '@internetstiftelsen/charts/chart-group';
120
+ import { XYChart } from '@internetstiftelsen/charts/xy-chart';
121
+ import { Line } from '@internetstiftelsen/charts/line';
122
+ import { Bar } from '@internetstiftelsen/charts/bar';
123
+ import { Legend } from '@internetstiftelsen/charts/legend';
124
+ import { Title } from '@internetstiftelsen/charts/title';
125
+
126
+ const lineChart = new XYChart({ data: lineData });
127
+ lineChart.addChild(new Line({ dataKey: 'revenue' }));
128
+
129
+ const barChart = new XYChart({ data: barData });
130
+ barChart.addChild(new Bar({ dataKey: 'revenue' }));
131
+
132
+ const group = new ChartGroup({
133
+ cols: 2,
134
+ gap: 20,
135
+ height: 420,
136
+ syncY: true,
137
+ });
138
+
139
+ group
140
+ .addChild(new Title({ text: 'Revenue vs Expenses' }))
141
+ .addChart(barChart)
142
+ .addChart(lineChart)
143
+ .addChild(new Legend());
144
+
145
+ group.render('#chart-group');
146
+ ```
147
+
148
+ Legend state now works even without mounting a `Legend` on each child chart, so
149
+ grouped charts can share one coordinated legend while preserving child tooltip,
150
+ axis, and responsive behavior. `ChartGroup.height` behaves like chart height:
151
+ set it for a fixed total group height, or omit it to size from the render
152
+ container. Set `syncY: true` when you want vertical `XYChart` children to share
153
+ the same Y domain so grid lines stay aligned while only one child renders a
154
+ visible Y axis.
155
+
156
+ `ChartGroup` also supports declarative responsive layout overrides. Group
157
+ breakpoints can change `cols` and `gap`, while `addChart(..., options)` can
158
+ override `span`, `height`, `order`, or `hidden` per child. Just like chart
159
+ responsive config, both `minWidth` and `maxWidth` are supported and all
160
+ matching breakpoints merge in declaration order:
161
+
162
+ ```typescript
163
+ const group = new ChartGroup({
164
+ cols: 3,
165
+ responsive: {
166
+ breakpoints: {
167
+ tablet: { maxWidth: 1023, cols: 2 },
168
+ mobile: { maxWidth: 640, cols: 1, gap: 16 },
169
+ },
170
+ },
171
+ });
172
+
173
+ group
174
+ .addChart(barChart, {
175
+ responsive: {
176
+ breakpoints: {
177
+ mobile: { maxWidth: 640, hidden: true },
178
+ },
179
+ },
180
+ })
181
+ .addChart(lineChart, {
182
+ span: 2,
183
+ responsive: {
184
+ breakpoints: {
185
+ mobile: { maxWidth: 640, span: 1, order: -1 },
186
+ },
187
+ },
188
+ });
189
+ ```
190
+
191
+ ## Divergent Bars
192
+
193
+ Bar charts always render from a zero baseline. When bar data contains both
194
+ positive and negative values, the bars automatically diverge around `0` in both
195
+ vertical and horizontal orientations.
196
+
197
+ ```javascript
198
+ import { XYChart } from '@internetstiftelsen/charts/xy-chart';
199
+ import { Bar } from '@internetstiftelsen/charts/bar';
200
+ import { XAxis } from '@internetstiftelsen/charts/x-axis';
201
+ import { YAxis } from '@internetstiftelsen/charts/y-axis';
202
+
203
+ const chart = new XYChart({
204
+ data: [
205
+ { metric: 'Pricing', delta: -18 },
206
+ { metric: 'Feature set', delta: 24 },
207
+ { metric: 'Support', delta: 11 },
208
+ ],
209
+ orientation: 'horizontal',
210
+ });
211
+
212
+ chart
213
+ .addChild(new XAxis({ dataKey: 'metric' }))
214
+ .addChild(new YAxis())
215
+ .addChild(new Bar({ dataKey: 'delta' }));
216
+ ```
217
+
218
+ Automatic numeric bar domains always include `0`. If you configure an explicit
219
+ numeric domain or `min`/`max` for the bar value axis, that final domain must
220
+ still include `0`.
221
+
222
+ Categorical `y` axes now preserve data order from top to bottom by default.
223
+ Use `scales.x.reverse` or `scales.y.reverse` when you want to intentionally flip
224
+ an axis direction.
225
+
93
226
  Responsive overrides are declarative and merge all matching breakpoints in
94
227
  declaration order:
95
228
 
@@ -211,6 +344,7 @@ Grouped parsing rules:
211
344
 
212
345
  - [Getting Started](./docs/getting-started.md) - Installation, Vanilla JS, React integration
213
346
  - [XYChart](./docs/xy-chart.md) - Line, area, and bar charts API
347
+ - [ChartGroup](./docs/chart-group.md) - Combined chart layouts with a shared legend
214
348
  - [WordCloudChart](./docs/word-cloud-chart.md) - Word frequency visualization API
215
349
  - [DonutChart](./docs/donut-chart.md) - Donut/pie charts API
216
350
  - [PieChart](./docs/pie-chart.md) - Pie chart API
package/dist/bar.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Selection } from 'd3';
2
- import type { BarConfig, BarStackingContext, BarValueLabelConfig, ChartTheme, D3Scale, DataItem, ScaleType, ExportHooks, BarConfigBase } from './types.js';
2
+ import type { BarConfig, BarStackingContext, BarSide, BarValueLabelConfig, ChartTheme, D3Scale, DataItem, Orientation, 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";
@@ -7,11 +7,13 @@ export declare class Bar implements ChartComponent<BarConfigBase> {
7
7
  readonly fill: string;
8
8
  readonly colorAdapter?: (data: DataItem, index: number) => string;
9
9
  readonly maxBarSize?: number;
10
+ readonly side: BarSide;
10
11
  readonly valueLabel?: BarValueLabelConfig;
11
12
  readonly exportHooks?: ExportHooks<BarConfigBase>;
12
13
  constructor(config: BarConfig);
13
14
  getExportConfig(): BarConfigBase;
14
15
  createExportComponent(override?: Partial<BarConfigBase>): ChartComponent<BarConfigBase>;
16
+ getRenderedValue(value: number, orientation?: Orientation): number;
15
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, orientation?: 'vertical' | 'horizontal'): void;
16
18
  private renderVertical;
17
19
  private renderHorizontal;