Releases: techniq/layerchart
layerchart@2.0.0-next.53
Minor Changes
-
feat: Support pre-projected topologies in
GeoLegendviareferenceScale(#449)Add a
referenceScaleprop toGeoLegendfor charts that render pre-projected data withgeoIdentity(e.g.us-atlas'scounties-albers-10m/states-albers-10m, pre-projected withgeoAlbersUsa().scale(1300)). When provided, pixels-per-distance is derived from the chart's fit scale and the supplied base scale, bypassing theprojection.invert+geoDistancepath which only works for real lon/lat projections. TheGeoPathbubble-map example now renders a correct scale bar.
layerchart@2.0.0-next.52
Minor Changes
-
feat(ArcLabel): New component for positioning text labels on arc segments (#817)
ArcLabelis a new marking component for placing text (and optional leader lines) relative to an arc. It's used internally byPieChartandArcChartwhen thelabelsprop is set, but can also be rendered directly inside anArcchildren 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 uprightcentroid-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 viastartOffset: '50%'by default)callout— outside the arc with a leader line that bends horizontally to the label
ArcLabelaccepts a singleoffsetprop that is routed to the placement-appropriate radial padding (centroid offset,innerPadding/outerPadding, orcalloutLineLength), pluscalloutLineLength/calloutLabelOffset/calloutPaddingfor fine-grained control of callout leader lines. The leader line renders via thePathprimitive, so it works in both SVG and Canvas chart layers. -
breaking(Arc): Center arc text along path by default for
inner/middle/outerpositions (#817)getArcTextProps('inner' | 'middle' | 'outer')now defaults tostartOffset: '50%'withtextAnchor: 'middle', centering the text along the arc path rather than anchoring it at the arc start. When an explicitstartOffsetis 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
innerPaddingoption togetArcTextProps/getTrackTextProps(#817)ArcTextOptionsnow supports aninnerPaddingoption, symmetric to the existingouterPadding. Positive values shrink the inner radius used to build theinner/middlearc text paths, moving text inward (toward the chart center). Previously, offsetting aninner-placed arc label away from the arc edge required overriding the path manually; now it works the same asouterPaddingdoes foroutertext. -
feat(CircleLegend): New component for visualizing radius (
rScale) values as nested circles (#818)CircleLegenddisplays 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 readsrScalefrom the chart context, but ascaleprop can also be passed to render standalone.Supports
tickValues/ticks/tickFormatfor value selection and formatting, atitlerendered centered above the circles, andlabelPlacement="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
Chartprojection (#818)GeoLegendreads 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, butdistancecan be passed for an explicit value. Supportsunits="km" | "mi", configurableticks,tickFormat,title, and the standardplacementprops. Inspired by Harry Stevens' d3-geo-scale-bar. -
feat(Labels): Add
middleplacement and changecenterto 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 previouscenterbehavior (label aligned to the value edge with a middle anchor) is now available as the newplacement="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, andCircleLegenddraws a 50%-opacity filled circle at the corresponding radius. Both auto-read the hovered data fromctx.tooltip.dataand pipe it through the chart's color (ctx.c) / radius (ctx.r) accessors, so wiring is automatic for charts that configurec/r/cScale/rScaleviaChartprops.A new
valueprop 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/scaleQuantilescales, theLegendindicator centers on the matching bucket swatch. -
feat(PieChart/ArcChart): Add top-level
labelsprop (#817)PieChartandArcChartnow accept alabelsprop that renders text labels on each arc without requiring a customarcsnippet. Passtrueto enable defaults (centroid placement, default value accessor), or an object to configure anyArcLabelprops — 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
Minor Changes
-
feat: New
GeoRastercomponent 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()tolayerchart/serverfor server-side chart-to-image rendering (PNG/JPEG) (#813)
Patch Changes
-
feat: Add
strokeandfillprops toAxisandGridfor 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
translateto container center whentranslateandfitGeojsonare 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
asassertions from exported Svelte markup in core mark components so preprocessors that parse markup expressions as plain JavaScript can consume packaged components without failing
- Remove TypeScript-only
layerchart@2.0.0-next.50
Minor Changes
-
feat: New Trail component for variable-width lines (#449)
-
fix(Axis): Default
tickSpacingtonullfor categorical band scales, showing all ticks by default instead of reducing them. UsetickSpacing={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
Minor Changes
-
feat(Labels): Add
smartplacement 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,
scaleExtentandtranslateExtentare now interpreted as relative values (like d3-zoom).scaleExtent: [0.5, 8]means 0.5x to 8x of the fitted projection scale.translateExtentis offset from the initial fitted position in pixels. (#449) -
feat(Spline): Support function-valued
stroke,fill, andopacityfor per-segment styling (#449) -
feat(Text): Add
formatprop and tween numericvaluewhenmotionis configured (#449)
Patch Changes
-
Support
tickSpacingfor 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 nomotionprop is provided, avoiding$state/$effectoverhead per axiscreateDataMotionMap: Short-circuit whenmotionisundefined, skippingparseMotionPropoverheadcreateKey: Only create fill/stroke key trackers in canvas layer (skipped for SVG/HTML)registerComponent: SkipregisterMarkfor emptyMarkInfo(pixel-mode marks)- All primitives: Skip
$effectfor data motion tracking when no motion is configured - Rect/Image: Avoid per-axis
parseMotionPropcalls whenmotionisundefined
-
feat(Marker): Add
squareandsquare-stroketypes (#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
processTranslateanddisablePointerto 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: truein defaulttransformApplyfor globes. (#449) -
feat(Raster, Contour): support bounded geo raster overlays with projected interpolation (#449)
-
feat: Add Month component (#671)
-
fix(LinearGradient, RadialGradient): Register as
groupinstead ofmarkin canvas component tree so wrapped children (e.g. Arc, Path) are rendered (#449)
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)
layerchart@2.0.0-next.47
Major Changes
-
breaking(BrushContext|TransformContext): Rename
bind:brushContext/bind:transformContexttobind:state(#663)Both
BrushContextandTransformContextnow usebind:stateinstead of their previous named bindings. Additionally, properties onChartStatehave 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'todomainExtent: 'data'(#663)The
'original'value fordomainExtenthas 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
GeoContextcomponent toGeoProjection(#663)The
GeoContextcomponent has been renamed toGeoProjectionto 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()supportedContextsprop →layersprop on components- Internal
layout/directory moved tolayers/(affects deep imports)
- import { getRenderContext } from 'layerchart' + import { getLayerContext } from 'layerchart'
-
breaking(Chart): Remove
isVerticalfrom ChartState, addvalueAxisprop toChart(#663)ChartState.isVerticalhas been removed in favor ofChartState.valueAxis('x'|'y'), which explicitly defines which axis represents the value (dependent variable).Simplified charts (
BarChart,LineChart,AreaChart,ScatterChart) still accept theorientationprop as before — each chart maps it to the correctvalueAxisinternally. The<Chart>component itself now usesvalueAxisdirectly, sinceorientationis ambiguous at that level (a "vertical" BarChart hasvalueAxis="y"while a "vertical" LineChart hasvalueAxis="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()→ usegetChartContext().tooltipgetBrushContext()/setBrushContext()→ usegetChartContext().brushStategetTransformContext()/setTransformContext()→ usegetChartContext().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
tooltipContextto simpletooltip(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,outliersaccessors) and automatic computation from raw values via thevaluesprop. Orientation-aware viavalueAxiscontext. -
feat: Add statistical utility functions
computeBoxStats()andkde()(#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 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
densityprop or automatic KDE from raw values viavaluesprop. Optionalboxandmedianoverlays. Configurablebandwidth,thresholds, andcurve. -
feat(Spline): Support geo projection (#663)
-
feat: Add geo projection support for primitives (Circle, Rect, etc) (#663)
-
feat(Highlight): Add
rprop to scale highlight points using the chart's rScale. Supportsr={true}to use the chart's r config or a custom accessor. (#663) -
breaking(Brush): Redesign brush API (#663)
Breaking changes:
- Remove
modeprop ('integrated' | 'separated') — sync behavior is now driven by presence ofx/yprops - Remove
resetOnEnd— calle.brush.reset()in youronBrushEndhandler instead - Remove
ignoreResetClick— replaced byclickToReset(defaulttrue) - Remove
onResetevent — checkbrush.active === falseinonBrushEnd/onChangeinstead
New features:
- Add
BrushState.move({ x?, y? })for programmatic selection control (like d3'sbrush.move()) - Add
BrushState.selectAll()to select the full domain extent - Add
BrushState.reset()to clear the selection - Add
clickToResetprop (defaulttrue) - Add
zoomOnBrushprop on Chart for simplified charts to opt into brush-to-zoom - Move domain clamping, edge adjustment, and range computation logic into
BrushStateclass - Add
BrushChartContextinterface for easier testing
- Remove
-
feat: Unified component tree for Canvas rendering with proper Group transform scoping. Fixes #662 (#663)
- New
registerComponentNode({ name, kind, canvasRender })API replaces bothregisterCanvasComponentand theInsideCompositeMarkboolean 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_skipRegistrationprops. - Removed
retainStateandnamefromComponentRendertype — Group's transform scoping is handled by tree position, and component names live on the tree node.
- New
-
feat: add
downloadImage,downloadSvg,getChartImageBlob, andgetChartSvgStringutilities to export charts as PNG/JPEG/WebP images or SVG files (#663) -
feat(SeriesState): Support passing
selectedas 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 optionaldataprop 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 throughcScale, 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 owny. Works for both horizontal (valueAxis='y') and vertical (valueAxis='x') charts. - Per-mark
dataprops are included in the chart's domain calculation automatically. - Implicit series are generated from mark registrations when no explicit
seriesprop is provided, enabling tooltip and legend support without requiring series definitions.
- Marks (Spline, Area, Points, Bars) now register their data, accessors, and colors with the Chart via
-
feat: Add inertia (momentum) support for transform drag gestures (#663)
-
breaking(Chart): Rename
tooltipprop totooltipContextto better describ...
layerchart@2.0.0-next.46
layerchart@2.0.0-next.45
Major Changes
- feat: New docs site (#449)
Minor Changes
-
breaking: Extract
Pathprimitive component fromSplinefor better separation of concerns (#659) -
breaking: Rename simplified charts
renderContextprop tolayer(#659) -
breaking: Change
defaultChartPadding(axis, legend)todefaultChartPadding({ axis, legend })and support overrides (ex.defaultChartPadding({ left: 50 })) (#659)
Patch Changes
-
feat(Chart): Support passing explicit
widthandheightinstead of requiring parent dimensions (#659) -
feat: Support global settings (layer type, debug, etc) (#659)
-
feat(Layer): Allow
typeto be optional, fallbacking back tosettings.layertype (#659) -
feat(Chart|Svg|Html): Support passing
clipprop 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
abovesnippet (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
styleattribute (#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
classprop (#659) -
refactor: Move contexts to separate
$lib/contextsmodule (#659) -
refactor: Removed lodash-es dependency (#659)
layerchart@1.0.13
Patch Changes
- fix(Canvas): Fix pointer events (hit canvas) when using Brave browser with fingerprinting protection enabled (#755)