New: bars Module
A brand-new ggplot2-aligned declarative bar chart module (bars) that reproduces disparate bar chart implementations across the gsm ecosystem, including most functionality in the existing, KRI-specific barChart module (#502, #482). Highlights include:
- Spec-driven API — define charts with a declarative
specobject (fill, position, scales, labels, theme, tooltip, etc.) - Position modes —
stack(default),fill(within-category percentage normalization),dodge(side-by-side), and layered positioning - Stat modes —
count(default) andpercent - Dynamic category axis — legend-driven axis subsetting that hides categories with no visible data (#503)
- Dynamic sizing — automatically adjusts chart height based on category count
- Dense legend — compact legend with tooltip on hover (#494)
- Zoom support — optional
chartjs-plugin-zoomintegration (#524) - Tick truncation & rotation — automatic categorical tick label truncation and rotation for long labels (#531)
- Selection & highlight API — programmatic selection/highlight with
selectCategories(),highlightCategories(), andclearSelection()methods - Click & hover callbacks —
onClickandonHoverhooks for interactive workflows (#488) - Reference lines — generic annotation-based reference lines with customizable styles (#498)
- Label annotations — in-bar segment labels, total labels, and dynamic contrast coloring (#487)
- Top-N limiting —
spec.nCategoriesto show only the top N categories (#493) - Captions — user-defined chart footnotes via
labels.captionsandlabels.captionsOptions - Export to PNG —
exportImage()helper for one-click PNG download (#499) - Tooltip formatting —
tooltip.formatandtooltip.formatterconvenience API with template string support (#489, #515) - Custom fill colors —
scales.fill.colorsnamed color map (#496) updateData/updateSpec— update chart data or spec without full re-render
New: facetBars Module
A new faceting layer for bars that renders multiple linked sub-charts (#492):
- Faceted layout — split data by a facet variable into separate sub-charts
- Linked interactions — hover highlight syncs across all facets
- Configurable scales —
facet.scales.x.freetoggles between constant and free category domains - Per-facet ordering — function-based x-axis order per facet panel
- Chart height control —
facet.chartHeightoption for sub-chart sizing - Selection sync — selection state synchronized across faceted charts
- Global category computation — consistent category ordering across facets
New: Bar Chart Builder
An interactive UI for constructing bars specifications:
- Visual controls for position, fill, sort, scales, tooltip, and export
- Live spec preview with JSON export
- Zoom control integration
New: Documentation Site
- Docsify-based documentation deployed to gh-pages
- Collapsible navigation sidebar across all example pages
- Module documentation differentiating between metric and generic chart modules
Enhancements
- scatterPlot: Generate scatter bounds on demand with backwards compatibility (#473)
- examples: KRI Facet, Retention, and Prevalence chart demonstrations
- examples: Side-by-side hover table and click-to-scatter workflows
Bug Fixes
- bars: Preserve legend colors during selection
- bars: Harden
truncateLabelagainst negative/NaNmaxLength - bars: Filter unknown fill values when
fill.orderis provided - bars: Coerce labels to string in
reorderDatasetsfor type-safe fill ordering - bars: Disable dynamic contrast color for
segment.placement='end' - bars: Empty dataset data on hide to prevent CategoryScale re-adding labels
- bars: Reset container dimensions on every render for
dynamicSizing - facetBars: Guard
setActiveElementsagainst undefined chart elements - facetBars: Re-apply
chartHeightafterbars()clears container height - facetBars: Restore key variable in
computeGlobalCategoriesfunction-order loop - facetBars: Pin category axis min/max for constant x domain
- facetBars: Resolve function
scales.x.orderincomputeGlobalScales - facetBars: Skip global category injection when
dynamicCategoryAxisis true - scatterPlot: Generate scatter bounds on demand with backwards compatibility (#473)
- Remove stray
console.logcalls
Infrastructure & Chores
- Add Husky pre-commit hook to rebundle on every commit
- OS/platform-agnostic npm scripts in
package.json - AI agent framework with TDD-first skills (
.agent/) - Issue templates for GitHub
- Remove unused React dependencies
- Dependency updates: lodash 4.18.1, esbuild 0.28.1, form-data 4.0.6, picomatch 2.3.2, minimatch 3.1.5, js-yaml 3.14.2, csvtojson 2.0.13, @babel/plugin-transform-modules-systemjs 7.29.4
What's Changed
- v2.3.0 by Spencer Childress (@samussiah) in #465
v2.3.0>devby Spencer Childress (@samussiah) in #468- Bump js-yaml from 3.14.1 to 3.14.2 by Dependabot (@dependabot)[bot] in #467
- Bump lodash from 4.17.21 to 4.17.23 by Dependabot (@dependabot)[bot] in #469
- Bump csvtojson from 2.0.10 to 2.0.13 by Dependabot (@dependabot)[bot] in #470
- Bump minimatch from 3.1.2 to 3.1.5 by Dependabot (@dependabot)[bot] in #472
- Bump picomatch from 2.3.1 to 2.3.2 by Dependabot (@dependabot)[bot] in #476
- Bump @tootallnate/once and jest-environment-jsdom by Dependabot (@dependabot)[bot] in #475
- fix: add scatterPlot predictBounds utility for issue #473 by Spencer Childress (@samussiah) in #474
- Bump lodash from 4.17.23 to 4.18.1 by Dependabot (@dependabot)[bot] in #477
- Bump @babel/plugin-transform-modules-systemjs from 7.20.11 to 7.29.4 by Dependabot (@dependabot)[bot] in #478
- feat: scaffold AI agent framework with TDD-first skills by Spencer Childress (@samussiah) in #504
- feat: add bars module with ggplot2-aligned spec API (#502, #482) by Spencer Childress (@samussiah) in #505
- Add support for bars as a percentage of the total for a given axis category. by Spencer Childress (@samussiah) in #506
- Add bars label annotations by Spencer Childress (@samussiah) in #507
- feat(bars): add scales.fill.colors named map and darkenHex guard (#496) by Spencer Childress (@samussiah) in #508
- feat(bars): tooltip format/formatter API + stable percentages on legend toggle (#489) by Spencer Childress (@samussiah) in #509
- feat(bars): add click and hover callback hooks (#488) by Spencer Childress (@samussiah) in #510
- feat(bars): add exportImage helper for PNG download by Spencer Childress (@samussiah) in #511
- feat(bars): add labels.captions and labels.captionsOptions for user-defined chart footnotes by Spencer Childress (@samussiah) in #512
- feat(bars): top-N category limiting (nCategories) by Spencer Childress (@samussiah) in #513
- feat(bars): add generic referenceLines annotation support by Spencer Childress (@samussiah) in #514
- feat(bars): enrich formatter details and add template string support by Spencer Childress (@samussiah) in #516
- feat(facetBars): faceted bar charts with linked interactions (#492) by Spencer Childress (@samussiah) in #518
- chore(deps-dev): bump esbuild from 0.25.12 to 0.28.1 by Dependabot (@dependabot)[bot] in #517
- Bump form-data from 4.0.5 to 4.0.6 by Dependabot (@dependabot)[bot] in #520
- feat(explorer): Data Explorer for bars/facetBars + facetBars bug fixes by Spencer Childress (@samussiah) in #521
- feat: add embedded position toggle to bars with fill mapping by Spencer Childress (@samussiah) in #523
- feat: add optional chartjs-plugin-zoom support to bars module by Spencer Childress (@samussiah) in #525
- feat(bars): add dense legend mode with tooltip on hover (#494) by Spencer Childress (@samussiah) in #526
- feat(bars): stacked, grouped, and layered bar position modes by Spencer Childress (@samussiah) in #528
- feat(bars): programmatic selection/highlight API by Spencer Childress (@samussiah) in #539
- feat(bars): add categorical tick label truncation and rotation (#531) by Spencer Childress (@samussiah) in #540
- fix: address v2.4.0 RC review findings by Spencer Childress (@samussiah) in #542
- Release Candidate: gsm.viz v2.4.0 by Spencer Childress (@samussiah) in #541
Full Changelog: v2.3.0...v2.4.0