feat(chart): combo charts with per-series kind and secondary value axis - #295
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds “combo chart” support across the authoring pipeline (builder → OOXML), parsing (readChartSpec), and SVG preview rendering, enabling per-series chart-kind overrides and optional secondary (right-side) value axis.
Changes:
- Extends
ChartSerieswithchartKindandsecondaryAxisto model combo charts. - Updates chart builder + reader to emit/parse multiple plot groups and secondary-axis wiring.
- Updates preview renderer + adds new tests to validate combo rendering and round-trip behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/preview-chart-combo.test.ts | Adds SVG assertions for combo rendering (bars + line overlay, right-side secondary ticks). |
| test/fn-chart-combo.test.ts | Adds end-to-end PPTX/XML + round-trip tests for combo plot groups and secondary axis emission. |
| src/internal/chartml/types.ts | Adds ChartSeries.chartKind and ChartSeries.secondaryAxis to the internal chart model. |
| src/internal/chartml/chart-reader.ts | Reads multiple plot groups and tags series with chartKind / secondaryAxis during parse. |
| src/internal/chartml/chart-builder.ts | Builds combo plot groups, introduces secondary axis pair emission, and routes groups to per-kind chart builders. |
| packages/preview/src/render-slide.ts | Adds combo-group rendering logic and right-side value-axis rendering for secondary axis. |
| .changeset/combo-chart-secondary-axis.md | Declares minor bumps + documents new combo chart capabilities. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+725
to
+736
| switch (kind) { | ||
| case 'column': | ||
| return buildBarChart(spec, sheet, 'col', seriesIndices, axes); | ||
| case 'bar': | ||
| return buildBarChart(spec, sheet, 'bar', seriesIndices, axes); | ||
| case 'line': | ||
| return buildLineChart(spec, sheet, seriesIndices, axes); | ||
| case 'area': | ||
| return buildAreaChart(spec, sheet, seriesIndices, axes); | ||
| default: | ||
| throw new Error(`combo chart: series chartKind '${kind}' is not authorable`); | ||
| } |
Comment on lines
684
to
+693
| const series: ChartSeries[] = []; | ||
| let categoriesFromFirst: string[] | null = null; | ||
| for (const ser of allChildElements(plotted, NAME_SER)) { | ||
| const serEntries: { ser: XmlElement; groupKind: ChartKind; secondary: boolean }[] = []; | ||
| for (const group of plotGroups) { | ||
| const secondary = groupUsesSecondaryAxis(group.element); | ||
| for (const ser of allChildElements(group.element, NAME_SER)) { | ||
| serEntries.push({ ser, groupKind: group.kind, secondary }); | ||
| } | ||
| } | ||
| for (const { ser, groupKind, secondary } of serEntries) { |
Comment on lines
+5111
to
+5117
| const isCombo = | ||
| isCartesian && | ||
| spec.kind !== 'bar' && | ||
| spec.series.some( | ||
| (s) => (s.chartKind !== undefined && s.chartKind !== spec.kind) || s.secondaryAxis === true, | ||
| ); | ||
| if (isCombo) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds combo-chart authoring + reading + preview rendering:
ChartSeries.chartKind('bar' | 'column' | 'line' | 'area') — per-series kind override, e.g. a line overlay on a column chart.ChartSeries.secondaryAxis: true— plots the series against a right-hand secondary value axis (<c:valAx axPos="r">+ deleted companion<c:catAx>), the standard PowerPoint combo layout for series with mixed units (counts vs. rates/scores).Builder
Series are split into plot groups keyed by (effective kind, axis); each group emits its own
<c:barChart>/<c:lineChart>/<c:areaChart>with the right<c:axId>pair. The secondary axis pair is emitted on demand. Non-combo base kinds (pie / doughnut / scatter / radar / bubble) reject the per-series fields with a clear error.Reader
readChartSpecnow walks every plot group in the plot area (previously only the first), tags series from non-first groups withchartKind, and detects secondary-axis membership from the group'saxId→valAx[axPos="r"]mapping. Round-trip safe.Preview
The renderer splits combo series into groups, scales each axis from its own series (
valueAxisbaked into filtered specs so all groups on one axis share a range), paints bars below line/area overlays, and draws secondary ticks + labels on the plot's right edge (AxisSpec.side: 'right').Test plan
test/fn-chart-combo.test.ts— XML shape (both plot groups, secondary axis pair, group→axis wiring),getShapeChartSpecround-trip, pie rejection.test/preview-chart-combo.test.ts— SVG assertions: bars + overlay path painted, right-edge secondary ticks at the secondary scale, single-kind path untouched.🤖 Generated with Claude Code
https://claude.ai/code/session_016az3UDqDkcNbCmWe3LoGnm