Skip to content

Releases: techniq/layerchart

layerchart@2.0.0-next.53

09 Apr 15:42
93e3b09

Choose a tag to compare

Pre-release

Minor Changes

  • feat: Support pre-projected topologies in GeoLegend via referenceScale (#449)

    Add a referenceScale prop to GeoLegend for charts that render pre-projected data with geoIdentity (e.g. us-atlas's counties-albers-10m / states-albers-10m, pre-projected with geoAlbersUsa().scale(1300)). When provided, pixels-per-distance is derived from the chart's fit scale and the supplied base scale, bypassing the projection.invert + geoDistance path which only works for real lon/lat projections. The GeoPath bubble-map example now renders a correct scale bar.

layerchart@2.0.0-next.52

09 Apr 12:55
85076f1

Choose a tag to compare

Pre-release

Minor Changes

  • feat(ArcLabel): New component for positioning text labels on arc segments (#817)

    ArcLabel is a new marking component for placing text (and optional leader lines) relative to an arc. It's used internally by PieChart and ArcChart when the labels prop is set, but can also be rendered directly inside an Arc children snippet.

    Supported placements:

    • centroid — at the arc centroid (horizontal text, default)
    • centroid-rotated — at the centroid, rotated to follow the arc tangent, flipped where needed so text stays upright
    • centroid-radial — at the centroid, rotated to read along the radial direction (center → outer edge)
    • inner / middle / outer — along the inner, medial, or outer arc path (centered via startOffset: '50%' by default)
    • callout — outside the arc with a leader line that bends horizontally to the label

    ArcLabel accepts a single offset prop that is routed to the placement-appropriate radial padding (centroid offset, innerPadding/outerPadding, or calloutLineLength), plus calloutLineLength / calloutLabelOffset / calloutPadding for fine-grained control of callout leader lines. The leader line renders via the Path primitive, so it works in both SVG and Canvas chart layers.

  • breaking(Arc): Center arc text along path by default for inner/middle/outer positions (#817)

    getArcTextProps('inner' | 'middle' | 'outer') now defaults to startOffset: '50%' with textAnchor: 'middle', centering the text along the arc path rather than anchoring it at the arc start. When an explicit startOffset is provided, the anchor falls back to 'start' so the text begins at that position (matching prior behavior for callers that set a start offset).

  • feat(Arc): Add innerPadding option to getArcTextProps / getTrackTextProps (#817)

    ArcTextOptions now supports an innerPadding option, symmetric to the existing outerPadding. Positive values shrink the inner radius used to build the inner/middle arc text paths, moving text inward (toward the chart center). Previously, offsetting an inner-placed arc label away from the arc edge required overriding the path manually; now it works the same as outerPadding does for outer text.

  • feat(CircleLegend): New component for visualizing radius (rScale) values as nested circles (#818)

    CircleLegend displays a set of bottom-aligned nested circles representing values from a radius scale, useful alongside bubble maps and scatter charts that encode magnitude via circle area. By default it reads rScale from the chart context, but a scale prop can also be passed to render standalone.

    Supports tickValues / ticks / tickFormat for value selection and formatting, a title rendered centered above the circles, and labelPlacement="right" | "left" | "inline" to render tick labels with a leader line on either side of the circles or centered inside each circle near the top.

  • feat(GeoLegend): New scale-bar legend showing real-world distance for the current Chart projection (#818)

    GeoLegend reads the active geo projection from the chart context and renders a labeled scale bar with tick subdivisions. By default it picks a "nice" round distance that covers ~25% of the chart width, but distance can be passed for an explicit value. Supports units="km" | "mi", configurable ticks, tickFormat, title, and the standard placement props. Inspired by Harry Stevens' d3-geo-scale-bar.

  • feat(Labels): Add middle placement and change center to center within the bar body (#449)

    placement="center" now positions the label at the center of the bar body (between the value edge and the baseline). The previous center behavior (label aligned to the value edge with a middle anchor) is now available as the new placement="middle".

  • feat(Legend, CircleLegend): Show an indicator of the current tooltip value on the legend (#818)

    Legend (ramp variant) now draws a small upward-pointing arrow below the color ramp at the position of the currently hovered value, and CircleLegend draws a 50%-opacity filled circle at the corresponding radius. Both auto-read the hovered data from ctx.tooltip.data and pipe it through the chart's color (ctx.c) / radius (ctx.r) accessors, so wiring is automatic for charts that configure c / r / cScale / rScale via Chart props.

    A new value prop on both components allows explicitly setting the indicator value (overriding the auto-detection), useful when the tooltip data shape doesn't match the chart's accessor.

    For scaleThreshold / scaleQuantize / scaleQuantile scales, the Legend indicator centers on the matching bucket swatch.

  • feat(PieChart/ArcChart): Add top-level labels prop (#817)

    PieChart and ArcChart now accept a labels prop that renders text labels on each arc without requiring a custom arc snippet. Pass true to enable defaults (centroid placement, default value accessor), or an object to configure any ArcLabel props — placement, offset, value accessor, callout line lengths, leader line style, text class, etc.

    <PieChart {data} labels={{ placement: 'callout', value: 'fruit' }} />

layerchart@2.0.0-next.51

07 Apr 16:46
c8a7c4d

Choose a tag to compare

Pre-release

Minor Changes

  • feat: New GeoRaster component for reprojecting raster imagery (e.g. NASA Blue Marble) onto any d3-geo projection via per-pixel inverse sampling on Canvas (#815)

  • feat: Add renderChart() to layerchart/server for server-side chart-to-image rendering (PNG/JPEG) (#813)

Patch Changes

  • feat: Add stroke and fill props to Axis and Grid for explicit color control (useful for SSR where CSS variables are unavailable) (#813)

  • fix: Skip mark x/y/data from domain/series calculation when geo projection is active (#449)

  • fix: Default geo projection translate to container center when translate and fitGeojson are not specified, instead of using d3-geo's fixed default ([480, 250]) (#815)

  • fix: improve compatibility with UnoCSS Svelte scoped preprocessing (#813)

    • Remove TypeScript-only as assertions from exported Svelte markup in core mark components so preprocessors that parse markup expressions as plain JavaScript can consume packaged components without failing

layerchart@2.0.0-next.50

04 Apr 01:18
7178eaa

Choose a tag to compare

Pre-release

Minor Changes

  • feat: New Trail component for variable-width lines (#449)

  • fix(Axis): Default tickSpacing to null for categorical band scales, showing all ticks by default instead of reducing them. Use tickSpacing={80} to opt-in to tick reducing on categorical band scale axes. (#449)

Patch Changes

  • fix(Spline): Make motion prop reactive so toggling between tween/none updates without remount (#449)

layerchart@2.0.0-next.49

02 Apr 19:28
0fb5400

Choose a tag to compare

Pre-release

Minor Changes

  • feat(Labels): Add smart placement option (#799)

    New placement="smart" mode that dynamically positions labels based on neighboring point values (peak, trough, rising, falling) to reduce overlapping.

  • feat(Chart, BrushState): Add band scale (categorical) support for transform pan/zoom and brush selection. Uses range-rescaling pattern to smoothly zoom and pan categorical bar charts. Automatically constrains panning to data boundaries and prevents zooming out past initial view. (#449)

  • feat(Chart): In projection mode, scaleExtent and translateExtent are now interpreted as relative values (like d3-zoom). scaleExtent: [0.5, 8] means 0.5x to 8x of the fitted projection scale. translateExtent is offset from the initial fitted position in pixels. (#449)

  • feat(Spline): Support function-valued stroke, fill, and opacity for per-segment styling (#449)

  • feat(Text): Add format prop and tween numeric value when motion is configured (#449)

Patch Changes

  • Support tickSpacing for band scales on Axis, thinning tick labels when the domain is larger than the available space. Automatically shows more tick labels when zoomed in on band scale transforms. (#449)

  • perf: Optimize primitive component instantiation (~3-5x faster for Rect, Circle, Ellipse, Line, Text, Path, Group) (#449)

    • createMotion: Fast-path passthrough when no motion prop is provided, avoiding $state/$effect overhead per axis
    • createDataMotionMap: Short-circuit when motion is undefined, skipping parseMotionProp overhead
    • createKey: Only create fill/stroke key trackers in canvas layer (skipped for SVG/HTML)
    • registerComponent: Skip registerMark for empty MarkInfo (pixel-mode marks)
    • All primitives: Skip $effect for data motion tracking when no motion is configured
    • Rect/Image: Avoid per-axis parseMotionProp calls when motion is undefined
  • feat(Marker): Add square and square-stroke types (#805)

  • fix(GeoPath): Fix canvas tooltip by conditionally passing onclick to Path, preventing non-interactive overlays from capturing hit canvas events (#449)

  • fix(scaleBandInvert): Account for range offset in band scale inversion. Previously assumed range started at 0, causing incorrect pixel-to-category mapping when the scale range was transformed. (#449)

  • fix(TransformContext): Reactively sync processTranslate and disablePointer to TransformState when props change. Fixes inverted globe dragging when dynamically switching between flat and globe projections. (#449)

  • fix(Chart): Enable scroll zoom for globe projections by including scale: true in default transformApply for globes. (#449)

  • feat(Raster, Contour): support bounded geo raster overlays with projected interpolation (#449)

  • feat: Add Month component (#671)

  • fix(LinearGradient, RadialGradient): Register as group instead of mark in canvas component tree so wrapped children (e.g. Arc, Path) are rendered (#449)

layerchart@2.0.0-next.48

31 Mar 17:47
f7fe3e3

Choose a tag to compare

Pre-release

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)

layerchart@2.0.0-next.47

31 Mar 15:26
4a93215

Choose a tag to compare

Pre-release

Major Changes

  • 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.brushContextchartContext.brushState
    • chartContext.transformContextchartContext.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 components
    • Internal layout/ 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().tooltip
    • getBrushContext() / setBrushContext() → use getChartContext().brushState
    • getTransformContext() / setTransformContext() → use getChartContext().transformState
    - import { getTooltipContext } from 'layerchart'
    - const tooltip = getTooltipContext()
    + import { getChartContext } from 'layerchart'
    + const chart = getChartContext()
    + // access via chart.tooltip
  • breaking(Arc|Pie|Calendar|GeoPath): Rename tooltipContext to simple tooltip (boolean), simplifying use case (#663)

Minor Changes

  • 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 method
    • kde(values, options?) computes kernel density estimation using the Epanechnikov kernel with Silverman's rule-of-thumb bandwidth
  • feat: 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:

    • Remove mode prop ('integrated' | 'separated') — sync behavior is now driven by presence of x/y props
    • Remove resetOnEnd — call e.brush.reset() in your onBrushEnd handler instead
    • Remove ignoreResetClick — replaced by clickToReset (default true)
    • Remove onReset event — check brush.active === false in onBrushEnd/onChange instead

    New features:

    • Add BrushState.move({ x?, y? }) for programmatic selection control (like d3's brush.move())
    • Add BrushState.selectAll() to select the full domain extent
    • Add BrushState.reset() to clear the selection
    • Add clickToReset prop (default true)
    • Add zoomOnBrush prop on Chart for simplified charts to opt into brush-to-zoom
    • Move domain clamping, edge adjustment, and range computation logic into BrushState class
    • Add BrushChartContext interface for easier testing
  • feat: Unified component tree for Canvas rendering with proper Group transform scoping. Fixes #662 (#663)

    • New registerComponentNode({ name, kind, canvasRender }) API replaces both registerCanvasComponent and the InsideCompositeMark boolean context with a single unified component tree.
    • Canvas rendering now walks the tree recursively with proper save()/restore() scoping, fixing Group transforms (translate, opacity) leaking to sibling components instead of only affecting children.
    • Composite marks (Area, Threshold, Hull, Labels, Grid) register as 'composite-mark' nodes, automatically preventing child marks from registering with the chart without manual _skipRegistration props.
    • Removed 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)

    • Marks (Spline, Area, Points, Bars) now register their data, accessors, and colors with the Chart via registerMark().
    • Chart automatically aggregates y/x accessors from marks, removing the need to pass y={['apples', 'oranges']} when each mark specifies its own y. Works for both horizontal (valueAxis='y') and vertical (valueAxis='x') charts.
    • Per-mark data props are included in the chart's domain calculation automatically.
    • Implicit series are generated from mark registrations when no explicit 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 describ...

Read more

layerchart@2.0.0-next.46

19 Feb 14:23
300e7dd

Choose a tag to compare

Pre-release

Patch Changes

  • fix: Workaround Svelte 5.52+ regression (Parse failure: Expected '{', got '(') (#449)

  • chore: Update deps (including dagre from 1.x to 2.x) (#449)

layerchart@2.0.0-next.45

18 Feb 15:50

Choose a tag to compare

Pre-release

Major Changes

  • feat: New docs site (#449)

Minor Changes

  • 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)

Patch Changes

  • 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)

layerchart@1.0.13

06 Jan 21:45
221f6da

Choose a tag to compare

Patch Changes

  • fix(Canvas): Fix pointer events (hit canvas) when using Brave browser with fingerprinting protection enabled (#755)