Waterfall
The createWaterfall helper accumulates a list of signed steps into floating bars: increases and decreases ride the running total, and total steps drop a full bar back to the base.
ts
// createWaterfall accumulates signed steps into floating bars — one series
// per direction (increase / decrease / total), each row filling exactly one.
import { createWaterfall } from '@mochart/core';
import type { MochartInputConfig } from '@mochart/core';
const waterfall = createWaterfall([
{ label: 'Product revenue', value: 420 },
{ label: 'Services revenue', value: 210 },
{ label: 'Gross revenue', total: true },
{ label: 'Cost of goods', value: -180 },
{ label: 'Operating expenses', value: -95 },
{ label: 'Marketing', value: -60 },
{ label: 'Tax', value: -22 },
{ label: 'Net income', total: true }
]);
export const config: MochartInputConfig = {
version: '1.0.0',
title: { text: 'Income Statement (fictional, $k)' },
categoryAxis: waterfall.categoryAxis,
// the returned fragment carries the axis base; merge your own settings over it
valueAxes: [{ ...waterfall.valueAxes[0], title: { text: '$ thousands' } }],
series: waterfall.series
};
export const data = waterfall.data;How it works
- Each item is
{ label, value }for a delta step, or{ label, total: true }for a total bar showing the running total so far (give a total avalueto reset the running total, e.g. an audited closing balance). Labels must be unique — they become the category values. - The helper returns
{ steps, data, categoryAxis, series, valueAxes }. The floating bars are three ordinarybarseries — increase, decrease, total — all spanning from the sharedstartproperty viarangeProperty. Every row carries a value for exactly one of them, andmissingValueMode: 'connect'withpartialRangeIsMissingkeeps the other two from rendering (startexists on every row, so withoutpartialRangeIsMissingthey would collapse to zero-height bars instead of skipping). Each slot shows one full-width bar while the legend still names the three directions. - The default direction colors are teal-green/red/blue rather than a pure green/red: green↔red is the classic red-green-blindness collision, and shifting the green toward teal keeps every pair distinguishable on light and dark surfaces. Override per direction with
colors, and rename the series withseriesTitles. basesets the value the running total starts from and total bars span from (default 0). It comes back invalueAxesas the axisbase— spread that fragment and the axis agrees with the bars, whatever the base is.- Each row also carries
delta,cumulativeanddirection, and the computed steps come back understeps— or callcomputeWaterfallSteps(items, base)alone for the math without the chart fragments. - Each bar spans from the running total before the step to the total after it, so a bar crosses or sits below the base as soon as the running total does. For bars rooted at the base whose own values carry the sign, see positive and negative values.