layerchart@2.0.0-next.48
Patch Changes
- fix(ChartState): Don't create spurious implicit series when mark accessor matches chart's own axis accessor, fixing domain corruption for heatmap/Cell charts (#449)
breaking(BrushContext|TransformContext): Rename bind:brushContext / bind:transformContext to bind:state (#663)
Both BrushContext and TransformContext now use bind:state instead of their previous named bindings. Additionally, properties on ChartState have been renamed:
chartContext.brushContext → chartContext.brushStatechartContext.transformContext → chartContext.transformState <BrushContext bind:brushContext>
<BrushContext bind:state>
<TransformContext bind:transformContext>
<TransformContext bind:state>breaking(TransformContext): Rename domainExtent: 'original' to domainExtent: 'data' (#663)
The 'original' value for domainExtent has been renamed to 'data' to better describe that it constrains pan/zoom to the data's domain bounds:
<Chart transform={{ domainExtent: 'original' }}>
<Chart transform={{ domainExtent: 'data' }}>breaking(GeoContext): Rename GeoContext component to GeoProjection (#663)
The GeoContext component has been renamed to GeoProjection to better describe its purpose. Update your imports and template usage:
import { GeoContext } from 'layerchart'
import { GeoProjection } from 'layerchart' <GeoContext projection={geoAlbersUsa}>
<GeoProjection projection={geoAlbersUsa}>breaking: Rename render context APIs to layer context (#663)
getRenderContext() → getLayerContext()setRenderContext() → setLayerContext()supportedContexts prop → layers prop on componentslayout/ directory moved to layers/ (affects deep imports) import { getRenderContext } from 'layerchart'
import { getLayerContext } from 'layerchart'breaking(Chart): Remove isVertical from ChartState, add valueAxis prop to Chart (#663)
ChartState.isVertical has been removed in favor of ChartState.valueAxis ('x' | 'y'), which explicitly defines which axis represents the value (dependent variable).
Simplified charts (BarChart, LineChart, AreaChart, ScatterChart) still accept the orientation prop as before — each chart maps it to the correct valueAxis internally. The <Chart> component itself now uses valueAxis directly, since orientation is ambiguous at that level (a "vertical" BarChart has valueAxis="y" while a "vertical" LineChart has valueAxis="x").
When accessing chart state:
if (chartContext.isVertical) { ... }
if (chartContext.valueAxis === 'y') { ... }When using <Chart> directly (not simplified charts):
<Chart ...>
<Chart valueAxis="x" ...>breaking: Remove standalone context getter/setter functions (#663)
The following standalone context functions have been removed in favor of the unified getChartContext() API:
getTooltipContext() / setTooltipContext() → use getChartContext().tooltipgetBrushContext() / setBrushContext() → use getChartContext().brushStategetTransformContext() / setTransformContext() → use getChartContext().transformState import { getTooltipContext } from 'layerchart'
const tooltip = getTooltipContext()
import { getChartContext } from 'layerchart'
const chart = getChartContext()
// access via chart.tooltipbreaking(Arc|Pie|Calendar|GeoPath): Rename tooltipContext to simple tooltip (boolean), simplifying use case (#663)
feat: Add BoxPlot component for box-and-whisker plots (#663)
New composite mark that renders whiskers, caps, IQR box, median line, and outlier dots. Supports both pre-computed statistics (min, q1, median, q3, max, outliers accessors) and automatic computation from raw values via the values prop. Orientation-aware via valueAxis context.
feat: Add statistical utility functions computeBoxStats() and kde() (#663)
computeBoxStats(values, k?) computes the five-number summary and outliers using the Tukey IQR methodkde(values, options?) computes kernel density estimation using the Epanechnikov kernel with Silverman's rule-of-thumb bandwidthfeat: Add Violin component for violin plots (#663)
New composite mark that renders a symmetric density curve (mirrored area) from raw data using kernel density estimation (Epanechnikov kernel). Supports pre-computed density data via density prop or automatic KDE from raw values via values prop. Optional box and median overlays. Configurable bandwidth, thresholds, and curve.
feat(Spline): Support geo projection (#663)
feat: Add geo projection support for primitives (Circle, Rect, etc) (#663)
feat(Highlight): Add r prop to scale highlight points using the chart's rScale. Supports r={true} to use the chart's r config or a custom accessor. (#663)
breaking(Brush): Redesign brush API (#663)
Breaking changes:
mode prop ('integrated' | 'separated') — sync behavior is now driven by presence of x/y propsresetOnEnd — call e.brush.reset() in your onBrushEnd handler insteadignoreResetClick — replaced by clickToReset (default true)onReset event — check brush.active === false in onBrushEnd/onChange insteadNew features:
BrushState.move({ x?, y? }) for programmatic selection control (like d3's brush.move())BrushState.selectAll() to select the full domain extentBrushState.reset() to clear the selectionclickToReset prop (default true)zoomOnBrush prop on Chart for simplified charts to opt into brush-to-zoomBrushState classBrushChartContext interface for easier testingfeat: Unified component tree for Canvas rendering with proper Group transform scoping. Fixes #662 (#663)
registerComponentNode({ name, kind, canvasRender }) API replaces both registerCanvasComponent and the InsideCompositeMark boolean context with a single unified component tree.save()/restore() scoping, fixing Group transforms (translate, opacity) leaking to sibling components instead of only affecting children.'composite-mark' nodes, automatically preventing child marks from registering with the chart without manual _skipRegistration props.retainState and name from ComponentRender type — Group's transform scoping is handled by tree position, and component names live on the tree node.feat: add downloadImage, downloadSvg, getChartImageBlob, and getChartSvgString utilities to export charts as PNG/JPEG/WebP images or SVG files (#663)
feat: Add Image component. Resolves #628 (#663)
feat(SeriesState): Support passing selected as part of series declaration (Ex. <Chart series={...}>) (#663)
feat: Add data mode to primitive components (Circle, Ellipse, Group, Line, Polygon, Rect, Text) (#663)
Primitives now accept string or function accessors for positional props (e.g. x="date", y={d => d.value}) to automatically resolve values through chart scales and iterate over data. Components also accept an optional data prop to override chart context data.
Color properties (fill, stroke) can also be data-driven, resolving per-item through the chart's color scale (cScale). String values are disambiguated: data property names resolve through cScale, while literal CSS colors pass through unchanged.
feat: Mark registration for automatic domain calculation, accessor aggregation, and implicit series (#663)
registerMark().y={['apples', 'oranges']} when each mark specifies its own y. Works for both horizontal (valueAxis='y') and vertical (valueAxis='x') charts.data props are included in the chart's domain calculation automatically.series prop is provided, enabling tooltip and legend support without requiring series definitions.feat: Add inertia (momentum) support for transform drag gestures (#663)
feat: Add Cell mark. Resolves #627. (#663)
breaking(Chart): Rename tooltip prop to tooltipContext to better describe purpose and fix conflict with new tooltip snippet (#663)
feat: Add Chord layout and Ribbon primitive (#663)
breaking(TransformContext): Rename initialScrollMode to scrollMode and make it reactive (#663)
feat(TransformContext): Add scrollActivationKey option to require a modifier key (meta, alt, control, shift) for scroll/wheel zoom/pan, preventing accidental page scroll from triggering transforms (#663)
feat(Transform): Add zoom/pan constraints (scaleExtent, translateExtent, constrain, domainExtent), replace geo.applyTransform with transform.mode: 'projection' | 'rotate', and reactively sync initial transform values on projection changes (#663)
feat(Bar): Support fixed width and height props to override scale-derived dimensions, centering the bar within its band. Resolves #360 (#663)
feat: Auto-compute Bar/Bars mount animation initial values from chart scales (#663)
Bar now automatically derives initialY/initialHeight (vertical) or initialX/initialWidth (horizontal) from the chart's scale range when motion is configured, removing the need to hardcode pixel values.
Also improves valueAxis inference on ChartState — when not explicitly set, it is now derived from scale types (band scale on y → valueAxis: 'x', band scale on x → valueAxis: 'y').
feat(Chart): Add cartesian pan/zoom via transform={{ mode: 'domain' }} with single or both axis support. Resolves #366 (#663)
feat(Spline): Add motion support for mount animation from baseline (#663)
feat: Support continuous color scales via cScale prop without requiring cRange (#663)
cScale (e.g. scaleSequential(interpolateTurbo)) to activate without cRange, enabling pre-configured sequential/diverging color scalescreateScale against undefined range to avoid breaking interpolator-based scalescDomain values and use extent instead of unique, producing correct [min, max] domains for continuous scalescScale color over default series color in tooltip/highlight when a color scale is configuredfeat(Labels): Support seriesKey in labels prop to filter which series renders labels. Resolves #633 (#663)
feat(Rect): New edge-based props (x0/x1/y0/y1) along with existing (x/y/width/height) and insets support (#663)
feat: Add Vector component (#663)
fix(Area): Default y0 baseline to chart's yBaseline when set (#663)
Area's y0 fallback now respects the chart's yBaseline prop (e.g. yBaseline={0} set by AreaChart) instead of always using min(yScale.domain()). This fixes areas filling to the bottom of the chart instead of to the baseline when data goes negative.
fix(Points|Labels): Correctly position when using x1 / y1 scales (issue #773) (#663)
refactor(Chart): Add debug prop and update settings context (#663)
fix: Default chart padding now applied when using ChartChildren layout (marks snippet) (#663)
When <Chart> is used with marks/grid/axis snippets (no explicit children snippet), default padding is now applied to match the axes that ChartChildren renders by default. When children is provided directly (e.g. Treemap, Pack), no default padding is applied since the user controls layout. This can still be overridden with explicit axis or padding props.
fix(Tooltip): Apply inverse transform for quadtree lookup when zoomed/panned (#663)
fix(Area): Handle degenerate domains (e.g. all-zero data) and unify y0/y1 baseline logic (#663)
[0, 0]), which caused yScale() to return NaN and break area path renderingfix(BarChart): automatically round the outer edge of each direction in stackDiverging layout (#663)
fix: flattenPathData now handles relative arc commands, fixing rounded bars starting below the baseline during mount animation (#663)
fix(Area|Highlight): Properly handling diveraging stack layouts for negative values (line, highlight point) (#663)
fix(Points|Labels): Correctly position when using array accessors (duration charts, etc). Fixes #633 (#663)
fix(TooltipContext): correct bisect-band hit detection by accounting for chart padding (#806)
fix(ClipPath): Support canvas layers. Resolves #660 (#663)
feat(Chart): Support motion prop to transition x/y scales using tween or spring (#663)
fix(Canavs): support strokeOpacity for Path component (#663)
fix(Text): handle inline styles and CSS class-based text-anchor (#663)
fix(Tooltip): Fade non-highlighted series items on hover to match chart highlight state (#663)
fix(TooltipContext): Support band mode with array-based range accessors (e.g. histograms using x={['x0', 'x1']}) (#663)
breaking: Extract Path primitive component from Spline for better separation of concerns (#659)
breaking: Rename simplified charts renderContext prop to layer (#659)
breaking: Change defaultChartPadding(axis, legend) to defaultChartPadding({ axis, legend }) and support overrides (ex. defaultChartPadding({ left: 50 })) (#659)
feat(Chart): Support passing explicit width and height instead of requiring parent dimensions (#659)
feat: Support global settings (layer type, debug, etc) (#659)
feat(Layer): Allow type to be optional, fallbacking back to settings.layer type (#659)
feat(Chart|Svg|Html): Support passing clip prop to hide overflown content (#659)
feat(Circle|Rect): Support passing children snippet for Html layers (#659)
feat(Layer): Support showing chart and full frame boundaries with settings.debug (#659)
fix(Threshold): Properly clip above snippet (resolving 1/2 width clipping issues when using Spline) (#659)
fix(AnnotationRange|TooltipContext|Highlight): Fix using interval scales with reversed data (ex. xReverse) (#659)
fix(Canavs): Support style attribute (#659)
fix(Canavs): Suppport dashed stroke (fix: #652) (#659)
fix(Rect): Support rounded (rx/ry) in Canvas layers (fixes #481) (#659)
fix(Bar): Fix browser lockup when switching between group and stack layouts (#659)
fix(Bar): Fix bar rounding direction when using xReverse/yReverse with interval scales (#659)
fix(Text): Support explicit "\n" and set line-height (to match svg/canvas) for html layers (#659)
feat(Chart): Support class prop (#659)
refactor: Move contexts to separate $lib/contexts module (#659)
refactor: Removed lodash-es dependency (#659)
start instead of always start of year (#657)