npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ibcs-react

v1.4.0

Published

IBCS / ISO 24896:2026 business reporting components for React: statement tables, variance and waterfall charts, KPI cards and a conformance linter. One data model, many views.

Readme

ibcs-react is a component library for IBCS / ISO 24896 business reporting - statement tables, variance charts, KPI cards and whole dashboards that encode the standard so reports come out consistent, comparable and decision-ready.

One data model, many views. The same statement feeds the table, the charts and the KPIs. Components never fetch - bring your data (a report engine, an API, static JSON) and they render a normalized model. Sign-explicit variances, four scenario fills (actual / previous / plan / forecast), shared scales, and a built-in checkIbcs conformance linter - among the first React libraries built around the IBCS / ISO 24896 notation.

Install

npm i ibcs-react

react and react-dom (>=18) are peer dependencies - they are not bundled.

Try it without installing: there's a runnable Next.js (App Router) starter in examples/nextjs - Open in StackBlitz ↗ (works once ibcs-react is published to npm).

AI agents

Building with a coding agent? Install the ibcs-react skills - IBCS notation rules, component recipes, and ibcs-report, which turns a financial workbook (a P&L, a balance sheet, a whole management pack) into a print-ready A4 board-report PDF drawn with ibcs-react components - packaged in the open SKILL.md format for Claude Code, Cursor, Codex and 70+ other agents:

npx skills add NibelungAI/ibcs-react              # pick from all three
npx skills add NibelungAI/ibcs-react@ibcs-report  # statements → board pack PDF

No install needed either - the skills are served raw from the docs site (overview), so telling an agent to “read ibcs.at/skills/ibcs-report/SKILL.md and follow it” is enough.

Agents can also read the docs directly: ibcs-react.com/llms.txt (index), llms-full.txt (whole corpus, one file), or any docs page as raw Markdown by appending .mdx to its URL - e.g. /docs/getting-started.mdx.

Quick start

import { KpiCard, StatementTable, Report } from "ibcs-react";
import type { StatementLine } from "ibcs-react";

// ONE data model - values keyed by scenario (AC actual / PY previous year /
// PL plan / FC forecast) - feeds every component.
const statement: StatementLine[] = [
  { id: "rev-product", label: "Product revenue", flow: "add", values: { AC: 17.2e6, PY: 16.1e6 } },
  { id: "rev-service", label: "Service revenue", flow: "add", values: { AC: 12.9e6, PY: 9.5e6 } },
  { id: "revenue", label: "Revenue", flow: "result", values: { AC: 30.1e6, PY: 25.6e6 } },
  {
    id: "cogs",
    label: "Cost of goods",
    flow: "subtract",
    higherIsBetter: false,
    values: { AC: 9.7e6, PY: 8.4e6 },
  },
  { id: "gm", label: "Gross margin", flow: "result", values: { AC: 20.4e6, PY: 17.2e6 } },
];

export function Dashboard() {
  return (
    <>
      <KpiCard
        label="Revenue"
        values={{ AC: 30.1e6, PY: 25.6e6 }}
        comparisons={["PY"]}
        format={{ compact: true, decimals: 1 }}
      />

      <StatementTable
        lines={statement}
        varianceColumns={[
          // right-hand variance panels, in order
          { base: "PY", mode: "abs", mark: "bar" }, // ΔPY as bars
          { base: "PY", mode: "pct", mark: "pin" }, // ΔPY% as pins
        ]} // ← this pair is also the default
        format={{ compact: true, decimals: 1 }}
      />
    </>
  );
}

Prefer to drive a whole page from data? Hand a ReportConfig to <Report />:

<Report
  config={{
    title: { who: "ACME Group", what: "Revenue & margin", when: "FY 2026" },
    columns: 12,
    blocks: [
      {
        id: "k1",
        type: "kpi",
        span: 4,
        config: { label: "Revenue", values: { AC: 30.1e6, PY: 25.6e6 }, comparisons: ["PY"] },
      },
      {
        id: "k2",
        type: "kpi",
        span: 4,
        config: { label: "Gross margin", values: { AC: 20.4e6, PY: 17.2e6 }, comparisons: ["PY"] },
      },
      { id: "s1", type: "statement", span: 12, config: { lines: statement } },
    ],
  }}
/>

The model

Everything is a tree of StatementLines carrying one value per scenario (AC actual, PY previous year, PL plan/budget, FC forecast):

  • flow: "add" / "subtract" move the actual-column waterfall; "result" draws a full subtotal bar without moving the running total.
  • higherIsBetter: set false on cost / expense / tax lines so an increase reads as unfavorable (red), even though the number is positive.
  • children: any line can be a collapsible group whose children carry the flow.

Components

All components are pure React + inline SVG. The library covers the complete IBCS template set - every standard chart (C01-C13) and table (T01-T04):

| Group | IBCS template | Component(s) | | ---------- | ---------------------------------------------- | ---------------------------------------------------------- | | Tables | T01 hierarchical rows · variance columns | DataTable, ComparisonTable | | | T02 hierarchical rows · integrated bar charts | ComparisonTable | | | T03 / T04 measure rows · integrated waterfalls | StatementTable | | | Budget / control matrix | MatrixTable | | Charts | C01 / C02 stacked column / stacked bar charts | StackedChart | | | C03 / C04 multi-tier column / bar charts | GroupedVarianceChart | | | C05 horizontal waterfall chart + columns | ColumnVarianceWaterfallChart, HorizontalWaterfallChart | | | C06 vertical waterfall chart + bars | BarVarianceWaterfallChart | | | C07 line · C08 area | LineChart · AreaChart, VarianceAreaChart | | | C09 scattergram · C10 bubble chart | ScatterChart · BubbleChart | | | C11 tree charts (calculation / ratio) | TreeChart, RatioTreeChart | | | C12 vertical waterfalls + variance | WaterfallChart, WaterfallStatementChart | | | C13 small multiples | SmallMultiples, MiniVarianceMultiples | | | (extras) integrated / ranking variance | IntegratedVarianceChart, RankingVarianceChart |

Tables (IBCS templates T01-T04)

  • StatementTable - the IBCS integrated waterfall (T03/T04): a P&L (flow) or balance sheet (mode="stock") with embedded variance bars/pins, expand/ collapse-all, optional virtualization (maxHeight) for large consolidations.
  • DataTable - the general cross-entity comparison table (T01): rows = entities, columns = measures (values, embedded variance bars/pins, sparklines).
  • ComparisonTable - the centre-label flanking layout (T01/T02): one measure with column groups (e.g. month vs YTD), each PY/PL/AC + variance.
  • MatrixTable - a budget / control matrix: a P&L row tree crossed with an expanding period column tree (Year → Quarter → Month), PL/AC/FC sub-columns, ΔBudget, sticky first column + horizontal scroll, expand-all periods.

StatementTable, DataTable and MatrixTable follow the React controlled/uncontrolled convention (ComparisonTable is a static layout with no interactive state). Seed them and let them own their state - defaultCollapsed, defaultSort, defaultExpandedRows / defaultExpandedCols - or take the state over with collapsed + onCollapsedChange, sort + onSortChange, expandedRows / expandedCols + onExpandedRowsChange / onExpandedColsChange, for URL sync, persistence or two views kept in step. The on…Change callbacks also fire in uncontrolled mode, as observers.

Charts

  • VarianceColumnChart - AC vs a comparison as overlapped columns (or pins) with an absolute/relative variance panel beneath.
  • TrendChart - a many-period time series (built for 13): AC solid / FC hatched columns, PY & PL reference lines, variance panel.
  • StructureChart - ranked horizontal bars for composition / contribution, AC vs PY overlap and % share.
  • WaterfallChart - the IBCS vertical waterfall chart (C12): a standalone add / subtract / result bridge.
  • StackedChart - the IBCS stacked column chart (C01, over time) or stacked bar chart (C02, over a structure), with category totals.
  • LineChart - dense multi-series time lines with markers (C07).
  • AreaChart - one scenario filled to the zero baseline (C08), optional reference line on top.
  • ScatterChart - a value/value scattergram (C09) with optional constant-product iso-lines (e.g. equal gross profit).
  • BubbleChart - two value axes plus a size dimension (C10).
  • ComboChart - columns + a secondary-axis line.
  • TreeChart / RatioTreeChart - the IBCS tree chart (C11), a calculation / DuPont tree: TreeChart shows a value per node, RatioTreeChart a mini time-series per node.
  • GroupedVarianceChart - the IBCS multi-tier column chart (C03) / multi-tier bar chart (C04): grouped two-scenario columns or bars with stacked absolute + relative variance tiers.
  • IntegratedVarianceChart - the signature vertical 3-tier chart: Δ% pins / Δ bars / AC columns with a PY-solid or PL-frame reference + FY total.
  • RankingVarianceChart - a sorted horizontal AC + plan-overlay chart with ΔPL bar and ΔPL% pin columns and a total row.
  • HorizontalWaterfallChart - the IBCS horizontal waterfall chart (C05); plus the composites ColumnVarianceWaterfallChart (C05), BarVarianceWaterfallChart (C06) and WaterfallStatementChart (C12, two side-by-side waterfalls + variance tiers).
  • VarianceAreaChart - actual vs a reference with green/red gap fill and a hatched forecast tail.
  • PieChart - a part-to-whole pie / donut and pie multiples. IBCS discourages pies; checkIbcs flags them - included for the occasional share.
  • SmallMultiples / MiniVarianceMultiples - a grid of the same chart repeated by a dimension (C13), with an opt-in shared scale (the IBCS CHECK rule).
  • VarianceBar - the standalone variance bar/pin primitive used inside the tables and charts.

KPI

  • KpiCard - a headline figure (count-up animated) with impact-coloured deltas vs PY/PL and an optional sparkline; an appearance prop controls border / background / corner radius / accent bar / shadow. The unit comes from format: currency for a leading symbol (€30.1M), suffix for a trailing one (18.4%), stated once beside the headline.
  • Sparkline - a tiny line / area / bar micro-chart for cards and cells.

Sizing & states

  • ChartBox / ResponsiveChart / ScrollChart - give a fixed-size chart its size: fit, alignment, padding and scroll (see Sizing). (ChartFrame is still exported, now deprecated in favour of ChartBox.)
  • Skeleton - a loading placeholder shaped like a chart / table / card, drawn as one self-animating SVG.
  • ChartState - loading / error / empty / content in a single wrapper, made to pair with useAsyncData ({ data, loading, error, refetch }).
  • ChartDataTable - a visually-hidden <table> of the numbers behind a chart, so screen readers get the values and not just a label.

Report builder

  • Report - renders a whole report from a JSON ReportConfig: a responsive grid of KPI / chart / statement / text / table blocks.
  • ConfiguredChart - renders any chart from a single ChartConfig object (the discriminated type selects the component).

Conformance

  • checkIbcs - lint a ChartConfig, KpiConfig or ReportConfig against the ISO 24896 / IBCS rules; returns findings (error / warning / info).
  • ConformanceReport - a React view that renders those findings.

Hooks

useStatement, useVariance, useVariances, useFilters, useLiveData, useAsyncData (API data with loading / refresh / abort / poll), useChartSelection (click-to-filter), useChartHover (+ ChartTooltip), usePrefersReducedMotion, useMountGrow, useAnimatedValue, useCountUp.

Helpers

downloadCSV, downloadTextFile, downloadSVG, downloadPNG, serializeSvg (browser-side export); ExportMenu (a ready SVG / PNG / CSV download menu).

Sizing

Every chart takes an explicit pixel width / height - nothing measures itself

  • so a render-prop wrapper resolves the size and the chart re-renders at it. Unlike scaling a bitmap, text and strokes stay crisp at any size.

  • ChartBox - the one to reach for, and the primitive the others are presets of. fit="scale" (default) fills the available width at the chart's aspect ratio and stops shrinking at minWidth (scrolling past it); "fixed" always draws the intrinsic size and scrolls; "contain" scales to fit both dimensions and letterboxes the rest; "fill" stretches to the box. Add align / verticalAlign, padding, background and scroll. Use it unless you need a shorter spelling.

  • ResponsiveChart - the minimal "fill the parent" wrapper: it measures its container with a ResizeObserver and hands integer width/height to the child. Give it an aspect to derive the height from the width (otherwise the measured height is used), with minWidth / minHeight / maxHeight clamps and an optional resize debounce.

  • ChartFrame - deprecated, use ChartBox. It framed a chart image-style inside a fixed box (fit="fill" / fit="contain", nine-point align / verticalAlign, padding, letterbox background) - all of which ChartBox does, with a fit union that is a superset of its two modes. It stays exported; just swap the tag name.

  • ScrollChart - the "one dimension fills, the other scrolls" preset: set height and the width fills, scrolling below minWidth; set width and the height scrolls inside a maxHeight viewport. Use it for a 13-period trend or a wide table on a phone.

<ChartBox width={760} height={300} fit="scale" minWidth={680}>
  {(w, h) => <TrendChart width={w} height={h} data={monthly} />}
</ChartBox>

All of them are SSR-safe: nothing is drawn until the container has been measured, so a chart never receives 0 or NaN and there is no layout jump.

One model, JSON config

KPIs, whole reports and the core chart set - 11 types (varianceColumn, trend, structure, waterfall, stacked, line, area, scatter, bubble, combo, tree) - are describable as plain serializable config objects; the specialist charts (pie, the variance-waterfall family, small multiples, ratio tree) are component-only. A report is data you can store, diff and round-trip:

import { ConfiguredChart, validateChartConfig, validateReportConfig } from "ibcs-react";

// Whatever the JSON editor / API / database hands you - hence `unknown`.
const raw: unknown = { type: "varianceColumn", data: quarterlyRevenue, comparison: "PY" };

const result = validateChartConfig(raw); // { ok: true, config } | { ok: false, error }
if (result.ok) return <ConfiguredChart config={result.config} />; // config is a typed ChartConfig

validateReportConfig does the same for a full ReportConfig before you hand it to <Report />. Because configs are JSON, you can persist a dashboard, ship it from a backend, or build a no-code editor on top.

ISO 24896 conformance

Most chart libraries let you draw anything. This one can also check a config against the IBCS notation - the basis of ISO 24896 - and tell you exactly where it departs from the standard before it ships:

import { checkIbcs } from "ibcs-react";

const findings = checkIbcs(reportConfig);
// [] when fully conforming; otherwise { rule, severity, message, ... } items,
// e.g. a bare-string title flagged for not using a Who/What/When structure.

Render the result with <ConformanceReport findings={findings} />. The encoded rule set is exported as IBCS_RULES.

Theming

All colors and scenario styles live in tokens and are overridable per component via the tokens prop (deep-merged):

import { StatementTable } from "ibcs-react";

<StatementTable lines={statement} tokens={{ color: { good: "#2e7d32", bad: "#c62828" } }} />;

Set the theme once for a whole subtree with IbcsThemeProvider instead of threading a tokens prop into every component:

import { IbcsThemeProvider, tokenPresets } from "ibcs-react";

<IbcsThemeProvider tokens={tokenPresets.cvd}>
  <KpiCard label="Revenue" values={{ AC: 30.1e6, PY: 25.6e6 }} />
  <StatementTable lines={statement} />
  {/* nearest wins - this one chart departs from the theme */}
  <TrendChart data={monthly} tokens={{ color: { bad: "#c62828" } }} />
</IbcsThemeProvider>;

Resolution order, nearest first: a component's own tokens prop, merged onto the nearest provider's theme, merged onto defaultTokens. Providers nest - an inner provider composes onto the outer one, so a full preset and a one-line tweak are the same operation. Building your own visual on ibcs-react/core? useIbcsTokens(override?) resolves exactly what the built-ins resolve, so it joins the same theme.

How cards and report blocks are framed is a token group as well (card): framedCard is the default hairline card, flatCard is whitespace alone - the IBCS SIMPLIFY look, and what a printed page wants:

import { Report, flatCard } from "ibcs-react";

<Report config={report} tokens={{ card: flatCard }} />;

The eight ship presets are collected in tokenPresets, keyed by stable ids (TokenPresetId) with display names in tokenPresetLabels - a typed theme switcher is one map over Object.keys(tokenPresets) - and also exported one by one:

| tokenPresets key | Label | Export | | ------------------ | ------------ | ---------------- | | default | Default | defaultTokens | | ocean | Ocean | oceanTokens | | azure | Azure | azureTokens | | greenRed | Green / Red | greenRedTokens | | vivid | Vivid | vividTokens | | cvd | CVD-safe | cvdTokens | | mono | Mono / print | monoTokens | | dark | Dark | darkTokens |

mergeTokens(override, base?) resolves a partial override into a full token set (base defaults to defaultTokens, so presets compose), and IbcsTokensOverride is the partial-token type to annotate your own theme objects with.

Next.js & React Server Components

The root entry ships with a "use client" directive. The components use hooks (hover, mount animation, container measurement), so importing ibcs-react from an App Router page marks that import as client code and it just works - no wrapper module of your own needed.

Server-side maths carries no such directive: import from ibcs-react/core in a server component, a route handler, a cron job or a build script to precompute statements, variances or a conformance check, then hand the plain data to a client component that renders it. There's a runnable starter in examples/nextjs.

ibcs-react/core - framework-agnostic

The pure logic ships under a separate entry with zero React dependency:

import {
  computeVariance,
  formatValue,
  statementToCSV,
  checkIbcs,
  defaultTokens,
} from "ibcs-react/core";

Reuse it to build a Vue/Svelte view, precompute statements on the server, or run conformance checks in CI - no DOM required.

License

MIT © ibcs-react contributors