All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Hover dot color matching — The hover indicator dot now automatically matches the hovered element's color (line stroke, area stroke, point fill) instead of hardcoded blue. Override with
frameProps={{ hoverAnnotation: { pointColor: "#custom" } }}. Fallback chain: explicitpointColor→ element color →--semiotic-primaryCSS var →#007bff. Affects all XY and Geo charts. pointColoroption onHoverAnnotationConfig— New opt-in override for hover dot color on Stream Frames.- Adaptive time tick formatting — New
adaptiveTimeTicks(granularity?)export fromsemiotic. Produces hierarchical axis labels: first tick is fully qualified, subsequent ticks only show what changed (e.g. seconds when the minute is the same, full timestamp when the hour rolls over). Tick labels auto-space based on label width to prevent overlap. - Forecast: training line styling —
trainStroke("darken" or CSS color),trainLinecap("round"),trainUnderline(true | "lighten"),trainOpacity,forecastOpacityonForecastConfig. Enables dashed training lines with solid underlines for visual distinction. - Forecast: per-datum anomaly styling —
anomalyColor,anomalyRadius, andanomalyStyleonForecastConfignow accept functions(datum) => valuefor data-driven anomaly rendering (e.g. sizing dots by anomaly count). - Forecast: multi-metric boundary duplication —
_groupByinternal field onForecastConfig. WhenlineByandforecastare both active, boundary points are duplicated within each metric group (not across groups), preventing stray cross-metric connecting lines in interleaved data. training-basesegment type — New segment for solid underlines beneath dashed training lines. PipelineStore renders training-base first (insertion order) so the solid line appears beneath the dashed one.resolveNodeColorshared utility — Extracted tosceneUtils.ts, used by both StreamXYFrame and StreamGeoFrame for consistent hover color resolution. HandlesCanvasPatternfills correctly.- 128 new unit tests — Multi-metric boundary duplication (3 tests), ThemeStore dark mode merging (5 tests), PipelineStore reproduction (9 tests), LineChart integration (8 tests), plus expanded statisticalOverlays coverage.
- SVGOverlay left axis label missing in dual-axis mode —
MultiAxisLineChartpasses left axis label viaaxesconfig, but SVGOverlay only read theyLabelprop (which is suppressed in dual-axis mode). Now readsleftAxis?.label || yLabel. - ThemeStore
mode: "dark"merged onto wrong base —{ mode: "dark", colors: { categorical: [...] } }was merging ontoLIGHT_THEME, so dark-mode text/background/grid colors were lost. Now correctly merges ontoDARK_THEME. - Tick label overlap on time axes — X-axis tick spacing now accounts for actual label width (estimated at 6.5px/char) instead of using a fixed 55px minimum, preventing label collision on dense time axes.
tickFormatsignature expanded —AxisConfig.tickFormatandxFormatnow receive(value, index, allTickValues)so formatters can produce hierarchical labels (e.g. show full date only on first tick or at boundary crossings).- Function accessors with forecast/anomaly — When
xAccessororyAccessoris a function, resolved values are now baked into data under__resolvedX/__resolvedYfields so the statistical overlay pipeline and annotation renderer can access them by string key. - Geo hover ring color — Geo frame point hover ring now uses
resolveNodeColor(shared utility) instead of inline logic, and correctly handlesCanvasPatternfills. - Tick color dark mode fallback — SVGOverlay tick color CSS var chain is now
--semiotic-text-secondary→--semiotic-text→#666, improving visibility when only--semiotic-textis set. - Annotation accessor fallback — SVGOverlay annotation renderer receives
"__resolvedX"/"__resolvedY"when accessors are functions, preventing annotations from rendering at wrong positions.
SegmentTypeunion expanded — Added"training-base"to the exported type.ForecastConfiginterface expanded — AddedtrainStroke,trainLinecap,trainUnderline,trainOpacity,forecastOpacity,anomalyStyle,_groupBy.anomalyColorandanomalyRadiusnow accept functions.- HOC early return guard — LineChart (and other HOCs with statistical overlays) no longer returns early before loading/empty state, ensuring all hooks are called unconditionally (React rules of hooks compliance).
Note: v3.1.1 was yanked from npm due to broken MCP tool schemas. Upgrade directly from 3.1.0 to 3.1.2.
- MCP server tools received no arguments — all 5 tools used empty
{}Zod schemas, causing the MCP SDK to strip all incoming parameters. Every tool call silently fell into "missing field" error paths. Fixed by defining proper Zod input schemas for all tools (getSchema,suggestChart,renderChart,diagnoseConfig,reportIssue). - MCP geo chart rendering —
renderHOCToSVGcalledvalidatePropswhich rejected geo components not in its validation map. Geo components (ChoroplethMap, ProportionalSymbolMap, FlowMap, DistanceCartogram) now skip validation and render correctly. - MCP
--portparsing —--httpwithout--portno longer produces NaN (falls back to 3001). - MCP "top-level fields" dead code — removed unreachable spread logic from
renderChart/diagnoseConfighandlers; updated Zod descriptions to match actual schema behavior (MCP SDK strips fields not in Zod schema). - suggestChart Histogram heuristic — removed unreachable
data.length >= 10check (suggestChart accepts 1–5 samples per its Zod schema). - renderHOCToSVG validation fragility — tightened unknown-component skip check to require exactly one "Unknown component" error instead of
.every()over all errors.
- MCP geo chart support — ChoroplethMap, ProportionalSymbolMap, FlowMap, and DistanceCartogram added to the MCP render registry (25 renderable components total).
- MCP HTTP transport —
npx semiotic-mcp --http --port 3001starts a session-based HTTP server with CORS headers for browser-based MCP inspectors and remote access. - suggestChart input validation — Zod schema enforces
.min(1).max(5)on data array.
- MCP
reportIssuetool — generates pre-filled GitHub issue URLs for bug reports and feature requests directly from AI coding assistants. No auth required. - MCP
getSchematool — returns the prop schema for a specific component on demand, reducing token overhead vs loading the full 63KB schema. Omitcomponentto list all 30 chart types. - MCP
suggestCharttool — analyzes a data sample and recommends chart types with confidence levels and example props. Supportsintentparameter for narrowing suggestions (comparison, trend, distribution, relationship, composition, geographic, network, hierarchy). - MCP server documentation — comprehensive setup instructions, tool descriptions, and usage examples in README.
- npm keywords —
mcp,model-context-protocol,mcp-server, and other discovery keywords for MCP directory indexing. - CI coverage thresholds — unit test coverage gated at 62/52/63/65% (statements/branches/functions/lines) with
@vitest/coverage-v8. - CI bundle size guardrails —
size-limitchecks for all 6 entry bundles in CI pipeline. - axe-core accessibility scanning — automated
@axe-core/playwrightscans across all chart category pages in E2E tests. - Self-healing error boundaries —
SafeRenderrunsdiagnoseConfigon chart failures (dev mode) and displays actionable fix suggestions alongside the error message. - 61 new unit tests — coverage for
withChartWrapper(SafeRender, warnDataShape, warnMissingField, renderEmptyState, renderLoadingState), network utilities, and push API on 7 ordinal chart types.
- MCP server — added
getSchema,suggestChart, andreportIssuetools (5 tools total). Added geo chart rendering support (ChoroplethMap, ProportionalSymbolMap, FlowMap, DistanceCartogram). - npm description — updated to highlight MCP server capability for discoverability.
prepublishOnlycleans dist/ — prevents stale dynamic import chunks from accumulating in published tarball.
- MCP
componentkey leaking into props — flat-shape calls like{ component: "LineChart", data: [...] }no longer passcomponentas a chart prop. - Missing dynamic import chunk —
dist/*-statisticalOverlays-*.jsadded tofilesarray so forecast/anomaly features work when consumed via ESM.
-
Geographic visualization — new
semiotic/geoentry point with 4 HOC chart components and a low-levelStreamGeoFrame, all canvas-rendered with d3-geo projections.ChoroplethMap— sequential color encoding on GeoJSON features. SupportsareaOpacity, function or stringvalueAccessor, and reference geography strings ("world-110m","world-50m", etc.).ProportionalSymbolMap— sized/colored point symbols on a geographic basemap withsizeBy,sizeRange, andcolorBy.FlowMap— origin-destination flow lines with width encoding, animated particles (showParticles,particleStyle), andlineType("geo"|"line").DistanceCartogram— ORBIS-style projection distortion based on travel cost. Concentric ring overlay (showRings,ringStyle,costLabel), north indicator (showNorth), configurablestrengthandlineMode.StreamGeoFrame— low-level geo frame with full control over areas, points, lines, canvas rendering, and push API for streaming.
-
GeoCanvasHitTester— spatial indexing for hover/click hit detection on canvas-rendered geo marks. -
GeoParticlePool— object-pool polyline particle system for animated flow particles. Supports"source"color inheritance, per-line color functions, and configurable spawn rate. -
GeoTileRenderer— slippy-map tile rendering on a background canvas. Mercator-only with retina support. ConfigurabletileURL,tileAttribution,tileCacheSize. -
Zoom/Pan — all geo charts accept
zoomable,zoomExtent,onZoom, with imperativegetZoom()/resetZoom()on the frame ref. Re-renders projection directly (no CSS transform). -
Drag Rotate —
dragRotateprop for globe spinning (defaults true for orthographic). Latitude clamped to [-90, 90]. -
Reference geography —
resolveReferenceGeography("world-110m")returns Natural Earth GeoJSON features.mergeData(features, data, { featureKey, dataKey })joins external data into features. -
Geo particles —
showParticlesandparticleStyleonFlowMapandStreamGeoFramefor animated dots flowing along line paths. -
6 geo documentation pages — ChoroplethMap, ProportionalSymbolMap, FlowMap, DistanceCartogram, StreamGeoFrame, and GeoVisualization overview.
-
2 geo playground pages — interactive prop exploration for geo charts.
-
1 geo recipe page — ORBIS-style distance cartogram walkthrough.
-
Geo test suites — unit tests for FlowMap (25 tests), ChoroplethMap (16 tests), DistanceCartogram (19 tests), colorUtils (+6 tests), hooks (+3 tests).
-
Accessibility foundation — moves Semiotic from ~30% to ~70% WCAG 2.1 AA compliance.
- Canvas
aria-label— every<canvas>element now has a computedaria-labeldescribing chart type and data shape (e.g., "scatter chart, 200 points"). All four Stream Frames:StreamXYFrame,StreamOrdinalFrame,StreamNetworkFrame,StreamGeoFrame. - Legend keyboard navigation — interactive legend items are focusable (
tabIndex={0},role="option"), withrole="listbox"on the container. Enter/Space activates (click), Arrow keys navigate between items. Visible focus ring on keyboard focus. aria-multiselectableon legend listbox whenlegendInteraction="isolate"orcustomClickBehavioris present.aria-selectedon legend items reflecting isolation state.aria-live="polite"region —AriaLiveTooltipcomponent mirrors tooltip text for screen reader announcements on hover.- SVG
<title>and<desc>— all SVG overlays (SVGOverlay,OrdinalSVGOverlay,NetworkSVGOverlay) includerole="img"and accessible<title>/<desc>elements derived from the chart title. aria-labelon ChartContainer toolbar buttons — Export, Fullscreen, and Copy Config buttons have descriptive labels and title attributes.- 35 Playwright integration tests —
integration-tests/accessibility.spec.tscovering canvas aria-labels, AriaLiveTooltip, legend keyboard traversal, focus rings, SVG title/desc, and ChartContainer toolbar buttons.
- Canvas
-
Streaming legend support — new
useStreamingLegendhook discovers categories from pushed data and builds legends dynamically with minimal re-renders via version counter. Integrated into StackedBarChart, PieChart, DonutChart, GroupedBarChart. -
Streaming regression test suite — 20+ Playwright integration tests (
streaming-regression.spec.ts) covering:- Canvas pixel sampling to verify colored fills (saturation > 0.1) across 8 streaming chart types
- Legend items appear after push API data arrives (4 chart types)
- Area chart tooltip contains numeric values, not dashes
- LineChart streaming stability (no "Maximum update depth" errors)
- Force graph content centroid within 30% of canvas center
- Error-free rendering across all 11 streaming test fixtures
-
Performance: color map cache —
PipelineStorecaches the category→color map across rebuilds using a sorted category set as cache key. Skips rebuild when categories are unchanged. (PipelineStore.ts) -
Performance: stacked area cache —
PipelineStorecaches stacked area cumulative sums using abuffer.size + ingestVersionhash. Skips expensive groupData + cumulative sum computation when data is unchanged. (PipelineStore.ts)
- Grey fills on push API charts — When using
ref.current.push(), HOC charts passed undefined color scales to style functions, causing grey fallback fills. Fixed end-to-end:- HOC
pieceStyle/pointStyle/lineStylefunctions now omit fill/stroke when colorScale is unavailable OrdinalPipelineStore.resolvePieceStylefills in from the frame's color scheme when HOC returns no fillPipelineStore.resolveLineStyle/resolveAreaStyle/point scene builder do the same for XY charts- New
resolveGroupColormethod provides centralizedSTREAMING_PALETTEassignment for streaming groups - Affected charts: StackedBarChart, PieChart, DonutChart, GroupedBarChart, BubbleChart, StackedAreaChart, AreaChart, LineChart, Scatterplot, QuadrantChart, ChordDiagram
- HOC
- LineChart infinite re-render loop — circular dependency between
useEffect→setSegmentAwareStyle→baseLineStyle→colorScale→statisticalResult. Fixed by guarding statistical effect to only run when forecast/anomaly is present and derivingeffectiveLineStylewithout unnecessary state. createColorScalecrash on undefined data — added null guards (d?.+.filter(v => v != null)) so push API charts with sparse data don't throw.OrdinalSVGOverlayduplicate React keys — keys now include category/group for uniqueness across stacked/grouped layouts.
- Area/StackedArea tooltips showing "-" —
hitTestAreaPathnow extracts the specific data point at the hover index (likehitTestLinedoes) instead of returning the entire data array. - Ordinal frame tooltips — default tooltip now shows category + value using
__oAccessor/__rAccessormetadata. - Geo chart tooltips — ChoroplethMap shows country names (not numeric IDs), ProportionalSymbolMap shows formatted metrics with labels, FlowMap shows source → target with values.
- Force graph centering — added
forceCenterto simulation, strengthenedforceX/forceY, clamped node positions to canvas bounds. FixedfinalizeLayoutoverwriting force-computed positions from stale bounding boxes during streaming warm-starts. - Streaming force refresh — force simulation now runs on topology changes during push API streaming.
- FIFO category ordering — streaming ordinal charts preserve insertion order instead of re-sorting by value (fixes violin/histogram column flicker).
- Edge hit areas — expanded to 5px minimum tolerance across XY lines, network edges (bezier + path), and geo lines. Added
pointToSegmentDistfor accurate perpendicular distance. Line hit tolerance now scales with stroke width. - Network edge ctx.lineWidth leak —
hitTestBezierEdgeandhitTestPathEdgenow save/restorectx.lineWidtharoundisPointInStrokecalls. - Sankey crossing reduction — added barycenter-based initial node ordering before iterative relaxation.
- QuadrantChart streaming — fixed quadrant backgrounds disappearing after first point; points now auto-color by quadrant when no
colorByprovided. - Anti-meridian line handling — geo lines that wrap across the projection edge are split into segments with smooth opacity fades.
- Distance cartogram centering — center node is pinned to viewport center during streaming.
- Orthographic drag jank — pointer-move rotations now coalesce via
pendingRotationRef, applying once per rAF frame.
- Orbit diagram — ring/connecting lines changed from
currentColor(invisible on canvas) torgba(128,128,128,0.35). Root nodes use scheme color instead of grey depth palette. - Treemap/CirclePack labels — luminance-based contrast text color (white on dark fills, dark on light fills). Treemap parent labels positioned at top-left of rectangle.
- ScatterplotMatrix diagonal histograms — now colored by category with O(1) Map lookups instead of grey fills with O(n)
.indexOf(). - Dark mode fixes — serialization page text contrast, streaming system model background, candlestick wick color, uncertainty tooltip background.
tooltip={false}now correctly disables tooltips on all 22 remaining HOCs. The patternnormalizeTooltip(tooltip) || defaultTooltipContentwas replaced with an explicittooltip === false ? undefined : ...check.normalizeTooltipunwrap heuristic tightened — the HoverData unwrap now only triggers when the object has.type === "node" | "edge"AND.data, preventing false unwraps when a user's datum has a.dataproperty.- ForceDirectedGraph empty state —
renderEmptyStatenow checksnodesinstead ofedges, so a graph with nodes but no edges no longer shows the empty state. - ChoroplethMap validation — added GeoJSON-aware validation that checks for a
geometryproperty on area features, replacing the inapplicablevalidateArrayDatacheck. - "Rendered more hooks than during previous render" in
FlowMapandChoroplethMap— hooks were called after early returns for loading/empty states. All hooks now run unconditionally before any early return. colorScalecrash with null areas in ChoroplethMap —useMemonow returns a fallback sequential scale whenresolvedAreasis null during async loading.- Variable name collision in ChoroplethMap — local
areaStylerenamed toareaStyleFnto avoid collision with destructured prop. - Function
colorByproduced undefined colors —useColorScalenow derives categories from data whencolorByis a function and builds a proper ordinal scale.getColormaps non-CSS-color strings throughcolorScale. - LineChart validation —
validateArrayDatanow receives the rawdataprop instead of post-processedsafeData, so push API mode (dataundefined) correctly skips validation instead of triggering "No data provided". - QuadrantChart
sizeDomainNaN —sizeByvalues are now filtered to finite numbers before computing min/max, preventing NaN propagation to point radius.
- Home page: meaningful tooltips on bar chart, bubble chart, network graph (degree centrality)
- Streaming sankey pastel colors, chord multi-color fix
- Highlight hover uses distinct red line, more distinctive custom theme
- Top/bottom legend examples, chart container year controls work
- Responsive frame data fix, styling offset fix, linked dashboard color consistency
- Candlestick dark mode, uncertainty tooltip dark mode, isotype chart person icons
- Radar/isotype duplicate key fix, network explorer
.datawrapper access - Rosling bubble annotations/extent/tooltip, benchmark log scale fix, forecast sparkline card
- Force graph sparse preset parameters, choropleth playground sizing
- DocumentFrame: added 100+ missing prop names to
processNodes - Tile map: production provider documentation
emphasisprop — all charts acceptemphasis="primary" | "secondary".ChartGriddetectsemphasis="primary"on children and spans them across two grid columns for F-pattern dashboard layouts.directLabelrendering — new"text"annotation type inannotationRules.tsxsodirectLabellabels actually render. Automatic right margin expansion prevents label clipping.gapStrategyfixes —"break"now correctly splits lines at null boundaries using synthetic_gapSegmentgroup keys."interpolate"filters gap points in the HOC before data enters the pipeline, preventingresolveAccessor's unary+from coercingnullto0.- Chart States docs page (
/features/chart-states) — dedicated page for empty, loading, and error state documentation. Moved from LineChart and ChartContainer pages. - Gap strategy tabs — consolidated three separate subsections in LineChart docs into a tabbed interface.
- Tabs component — reusable tab switcher for docs pages.
- Export default format —
exportChart()now defaults to PNG instead of SVG. PNG export composites the canvas data layer underneath the SVG overlay, producing a complete chart image. SVG export only captures the overlay (axes, labels). - Type widening — eliminated
as anycasts at HOC/Frame boundaries by wideningrFormat,oSort,colorBy, andTooltipFieldConfig.accessortypes in stream type definitions.
- Export captured only axes — PNG export now finds the
<canvas>element and draws it as the base layer before compositing the SVG overlay on top. directLabelannotations silently dropped —type: "text"was not a recognized annotation type; it fell through to the default case and returnednull.gapStrategy="break"drew lines through gaps — flattening re-merged segments because the Frame re-grouped by the originalgroupAccessor.gapStrategy="interpolate"dropped to zero —resolveAccessorused+(d)[key]which convertednullto0.colorBytype mismatch in network charts — hierarchy charts that color by depth index returned a number, but the type expected a string. AddedString()coercion.- Duplicate
amplitudeproperty inStreamOrdinalFrameProps.
Complete rewrite of Semiotic. Stream-first canvas architecture, 37 HOC chart components, full TypeScript, AI tooling, coordinated views, realtime encoding, and native server-side rendering.
Stream-first rendering. All frames are canvas-first with SVG overlays for
labels, axes, and annotations. Legacy frame names (XYFrame, OrdinalFrame,
NetworkFrame) have been removed entirely.
| Frame | Purpose |
|---|---|
StreamXYFrame |
Line, area, scatter, heatmap, candlestick charts |
StreamOrdinalFrame |
Bar, pie, boxplot, violin, swarm charts |
StreamNetworkFrame |
Force, sankey, chord, tree, treemap, circlepack |
Every frame supports a ref-based push API for streaming data.
Functional components + hooks. All components converted from class-based to
functional. Full TypeScript strict mode with generic type parameters on all
Frame and Chart components. "use client" directives for React Server
Components compatibility.
37 higher-order chart components that wrap the core Frames with curated, simple prop APIs.
XY Charts (wrap StreamXYFrame):
LineChart— line traces with curve interpolation, area fill, and point markersAreaChart— filled area beneath a lineStackedAreaChart— multiple stacked area seriesScatterplot— point clouds with color and size encodingConnectedScatterplot— sequential path through 2D space with Viridis gradientBubbleChart— sized circles with optional labelsHeatmap— 2D binned density visualization
Ordinal Charts (wrap StreamOrdinalFrame):
BarChart— vertical/horizontal bars with sort and color encodingStackedBarChart— stacked categorical barsGroupedBarChart— side-by-side grouped barsSwarmPlot— force-directed point distributionBoxPlot— statistical box-and-whiskerHistogram— binned frequency distributionViolinPlot— kernel density per categoryDotPlot— sorted dot stripsPieChart— proportional slicesDonutChart— ring variant of PieChart
Network Charts (wrap StreamNetworkFrame):
ForceDirectedGraph— force-simulation node-link diagramsChordDiagram— circular connection matrixSankeyDiagram— flow diagrams with weighted edgesTreeDiagram— hierarchical tree layoutsTreemap— space-filling hierarchical rectanglesCirclePack— nested circle packingOrbitDiagram— animated orbital hierarchy with solar/atomic/flat modes
Realtime Charts (canvas-based streaming):
RealtimeLineChart— streaming lineRealtimeHistogram— streaming histogram barsRealtimeSwarmChart— streaming scatterRealtimeWaterfallChart— streaming waterfall/candlestickRealtimeHeatmap— streaming 2D heatmaps with grid binning
All chart components feature:
- Full TypeScript generics (
LineChart<TDatum>) - Sensible defaults for width, height, margins, colors, hover
framePropsescape hatch for accessing the underlying Frame API- Automatic legend rendering when
colorByis set - Smart margin expansion to accommodate legends and axis labels
- Built-in error boundary (never blanks the page) and dev-mode validation warnings
Two SSR paths, both producing identical SVG output:
Component-level SSR — Stream Frames detect server context
(typeof window === "undefined") and render <svg> elements with scene
nodes instead of <canvas>. Same component, same props — works automatically
in Next.js App Router, Remix, and Astro.
Standalone SSR — semiotic/server entry point for Node.js environments
(email, OG images, PDF, static sites):
import { renderToStaticSVG } from "semiotic/server"
const svg = renderToStaticSVG("xy", {
lines: [{ coordinates: data }],
xAccessor: "date",
yAccessor: "value",
size: [600, 400],
})renderToStaticSVG(frameType, props)— generic entry pointrenderXYToStaticSVG(props)— XY-specificrenderOrdinalToStaticSVG(props)— ordinal-specificrenderNetworkToStaticSVG(props)— network-specific- Shared SceneToSVG converters used by both paths
decayprop — configurable opacity fade for older data (linear, exponential, step modes)pulseprop — glow flash effect on newly inserted data points with configurable duration/colortransitionprop — smooth position interpolation with ease-out cubic easingstalenessprop — canvas dimming + optional LIVE/STALE badge when data feed stops- All four features work on StreamXYFrame, StreamOrdinalFrame, and all realtime HOCs
- Features compose freely (e.g., decay + pulse creates a data trail with flash-on-arrival)
marginalGraphicsprop onStreamXYFrame,Scatterplot, andBubbleChart- Four types: histogram, violin, ridgeline, boxplot
- Margins auto-expand to 60px minimum when marginals are configured
LinkedCharts— cross-highlighting, brushing-and-linking, and crossfilter between any charts- Selection hooks:
useSelection,useLinkedHover,useBrushSelection,useFilteredData ScatterplotMatrix— N×N grid with hover cross-highlight or crossfilter brushingCategoryColorProvider— stable category→color mapping across charts
- Annotations with
type: "threshold"automatically split lines into colored segments - Interpolates exact crossing points between data samples
ThemeProviderwraps charts and injects CSS custom properties- Presets:
"light"(default) and"dark" useTheme()hook
ChartGrid— CSS Grid layout with auto columnsContextLayout— primary + context panel layout
semiotic/ai— HOC-only surface optimized for LLM code generationai/schema.json— machine-readable prop schemas for every component- MCP server (
npx semiotic-mcp) — renders charts as SVG tools for any MCP client- Per-component tools for all 21 SVG-renderable chart types
- Generic
renderCharttool accepting{ component, props } diagnoseConfigtool for anti-pattern detection
validateProps(componentName, props)— prop validation with Levenshtein typo suggestionsdiagnoseConfig(componentName, props)— anti-pattern detector with 12 checks:EMPTY_DATA,EMPTY_EDGES,BAD_WIDTH,BAD_HEIGHT,BAD_SIZE,ACCESSOR_MISSING,HIERARCHY_FLAT_ARRAY,NETWORK_NO_EDGES,DATE_NO_FORMAT,LINKED_HOVER_NO_SELECTION,MARGIN_OVERFLOW_H,MARGIN_OVERFLOW_V- CLI (
npx semiotic-ai) —--schema,--compact,--examples,--doctor CLAUDE.md— instruction file for Claude, Cursor, Copilot, Windsurf, and Cline- Schema freshness CI — cross-references schema.json, VALIDATION_MAP, and CLAUDE.md
onObservation— structured events (hover, click, brush, selection) on all HOCsuseChartObserver— aggregates observations across LinkedChartstoConfig/fromConfig/toURL/fromURL/copyConfig/configToJSX— chart serializationfromVegaLite(spec)— translate Vega-Lite specs to Semiotic configsexportChart()— download charts as PNG (default) or SVGChartErrorBoundary— React error boundaryDetailsPanel— click-driven detail panel insideChartContainer- Data transform helpers (
semiotic/data):bin,rollup,groupBy,pivot TooltipandMultiLineTooltipcomponents with field-based configuration- Keyboard navigation utilities
Eight separate entry points for reduced bundle sizes:
| Entry Point | Contents |
|---|---|
semiotic |
Full library |
semiotic/xy |
XY Frame + XY charts |
semiotic/ordinal |
Ordinal Frame + ordinal charts |
semiotic/network |
Network Frame + network charts |
semiotic/realtime |
Realtime charts |
semiotic/server |
SSR rendering functions |
semiotic/ai |
HOC-only surface for AI generation |
semiotic/data |
Data transform utilities |
Extracted shared logic from all HOC chart components into reusable hooks:
useChartSelectionhook — selection/hover setup used by 21 chartsuseChartLegendAndMarginhook — legend + margin auto-expansion used by 18 chartsbuildOrdinalTooltiphelper — shared tooltip builder for ordinal charts- Network utilities —
flattenHierarchy,inferNodesFromEdges,resolveHierarchySum,createEdgeStyleFn
- Rollup 2.x → Rollup 4.x with Terser minification
- Modern ESM output with
constbindings (ES2015 target) sideEffects: falsefor aggressive tree-shaking- Modern
exportsfield in package.json for proper ESM/CJS resolution
Minimum React version is now 18.1.0 (was 16.x in v1, 17.x in v2). Also supports React 19.
The monolithic processing/network.ts has been split into focused layout plugins:
sankey, force, chord, tree, cluster, treemap, circlepack, partition.
- All legacy frames —
XYFrame,OrdinalFrame,NetworkFrameand their Responsive/Spark variants. UseStreamXYFrame,StreamOrdinalFrame,StreamNetworkFrame. FacetController— useLinkedChartsRealtimeSankey,RealtimeNetworkFrame— useStreamNetworkFramewithchartType="sankey"baseMarkProps,ProcessViz,Mark,SpanOrDiv— removed internal utilities
- Chord diagram arc/ribbon angle alignment
- Stacked area streaming flicker (stable sort of groups)
- Violin plot IQR positioning
- Sankey particle colors
- Canvas clip region (marks no longer draw into margins)
- Tooltip position flipping at chart edges
- Stacked bar color encoding, streaming aggregation, and category flicker
- Force layout initial positions (phyllotaxis spiral)
- Treemap hover (smallest containing rect wins)
- Axis label floating-point noise and overlap
- ThemeProvider integration with SVG overlay axes and canvas background
- HOC chart data validation (visible error element instead of blank)
- 30+ additional rendering, theming, and coordination fixes
Version 2.0 was an internal milestone that began the transition from class components to functional components and introduced initial TypeScript support. It was never promoted to a stable release.
Notable changes from v1:
- Initial functional component conversions
- TypeScript adoption began
- React 17 compatibility
- Add
customClickBehaviorwith hover pointer state for legend interactions - Make difference between vertical and horizontal group rendering explicit
- Fix canvas interactivity with custom canvas function
For the complete v1.x changelog, see the git history.