|
1 | 1 | # LayerChart |
2 | 2 |
|
| 3 | +## 2.0.0-next.61 |
| 4 | + |
| 5 | +### Minor Changes |
| 6 | + |
| 7 | +- feat: Per-layer variants for primitives, compound marks, and high-level charts (`layerchart/svg`, `layerchart/canvas`, `layerchart/html`) ([#848](https://github.com/techniq/layerchart/pull/848)) |
| 8 | + |
| 9 | + Layer-agnostic components auto-detect the surrounding `<Svg>`, `<Canvas>`, or `<Html>` layer and bundle every render path. The new sub-path exports expose layer-specific variants so consumers committed to a single rendering layer can opt into a smaller bundle. |
| 10 | + |
| 11 | + ```ts |
| 12 | + // Default: agnostic, dispatches at runtime — works in any layer |
| 13 | + import { Rect, Circle, Text, Path, LineChart } from 'layerchart'; |
| 14 | + |
| 15 | + // SVG-only — skips canvas + html branches |
| 16 | + import { Rect, Circle, Text, Path, LineChart } from 'layerchart/svg'; |
| 17 | + |
| 18 | + // Canvas-only |
| 19 | + import { Rect, Circle, Text, LineChart } from 'layerchart/canvas'; |
| 20 | + |
| 21 | + // HTML-only — drops canvas + svg overhead (some primitives are ~95% smaller) |
| 22 | + import { Rect, Circle, Text, Pattern, LinearGradient } from 'layerchart/html'; |
| 23 | + ``` |
| 24 | + |
| 25 | + Each agnostic component (e.g. `Rect.svelte`) now dispatches to the corresponding per-layer variant under the hood (`Rect.svg.svelte`, `Rect.canvas.svelte`, `Rect.html.svelte`) — no breaking change for existing consumers. |
| 26 | + |
| 27 | + ### What's split |
| 28 | + |
| 29 | + **Primitives (13)** — the basic graphics building blocks |
| 30 | + `Circle`, `Text`, `Rect`, `Line`, `Path`, `Ellipse`, `Polygon`, `Group`, `Image`, `ClipPath`, `Pattern`, `LinearGradient`, `RadialGradient` |
| 31 | + |
| 32 | + **Compound marks (~30)** — chart axes, marks, annotations, and chart-relative shapes |
| 33 | + `Axis`, `Grid`, `Rule`, `Highlight`, `Layer`, `ChartChildren`, `ChartClipPath`, `CircleClipPath`, `Bars`, `Bar`, `Spline`, `Area`, `Pie`, `Arc`, `ArcLabel`, `Points`, `Cell`, `Frame`, `Threshold`, `Trail`, `Vector`, `Link`, `Labels`, `AnnotationLine`, `AnnotationPoint`, `AnnotationRange`, `Hull`, `Density`, `Voronoi`, `Contour`, `Raster`, `Violin`, `BoxPlot`, `Calendar`, `Month` |
| 34 | + |
| 35 | + **Geo components (`layerchart/geo`)** |
| 36 | + `GeoPath`, `GeoSpline`, `GeoPoint`, `GeoCircle`, `GeoTile`, `TileImage`, `Graticule`, `GeoClipPath`, `GeoEdgeFade` |
| 37 | + |
| 38 | + **Graph components (`layerchart/graph`)** |
| 39 | + `Ribbon` |
| 40 | + |
| 41 | + **High-level chart wrappers** — pre-composed charts with built-in tooltips, highlights, and series handling |
| 42 | + `LineChart`, `AreaChart`, `BarChart`, `ScatterChart`, `PieChart`, `ArcChart` |
| 43 | + |
| 44 | + The geo, graph, hierarchy, and force sub-paths also re-export every layer-agnostic helper they previously included, so a single `from 'layerchart/svg'` import covers a typical SVG chart end-to-end without falling back to `'layerchart'`. |
| 45 | + |
| 46 | + ### Standout per-layer wins (gz, vs agnostic baseline) |
| 47 | + |
| 48 | + **Primitives where the per-layer rendering is dramatically simpler:** |
| 49 | + - `Pattern` html: 14.81 → 0.92 KB (-94%) — HTML implementation is just CSS-string generation |
| 50 | + - `LinearGradient` html: 14.38 → 0.53 KB (-96%) |
| 51 | + - `Image` canvas: 14.95 → 3.73 KB (-75%) |
| 52 | + - `Text` svg/html: 29.13 → ~16 KB (-45%) |
| 53 | + - `Circle` / `Rect` / `Ellipse` / `Line` / `Path`: ~22–27% smaller per-layer |
| 54 | + |
| 55 | + **Compound marks:** typically 8–15% gz savings per-layer; outliers like `Highlight` (-30% canvas) and `Cell` (-22% svg) are larger because their HTML/canvas vs. SVG paths diverge significantly. |
| 56 | + |
| 57 | + **High-level charts:** ~5–12% gz savings (~5–11 KB) when imported from `layerchart/svg` or `layerchart/canvas`. A single-layer LineChart drops from 89.6 KB → 79.0 KB gz on the SVG path. |
| 58 | + |
| 59 | + For a consumer who migrates all imports to a single layer, cumulative savings across primitives and compound marks are 60–80 KB gz. |
| 60 | + |
| 61 | + ### Bundle reductions on the default `<Chart>` path |
| 62 | + |
| 63 | + In addition to opt-in per-layer variants, this release also makes a few previously-eager features lazy: |
| 64 | + - **`<TransformContext>`** is now dynamically imported when `<Chart transform={...}>` is set — saves ~2.8 KB gz on every chart that doesn't pan/zoom. |
| 65 | + - **`<BrushContext>`** was already lazy; nothing changes there. |
| 66 | + |
| 67 | + ### `<ChartCore>` for non-cartesian charts (new) |
| 68 | + |
| 69 | + A new `<ChartCore>` component is exported alongside `<Chart>` from each layer sub-path (`layerchart`, `layerchart/svg`, `layerchart/canvas`, `layerchart/html`). It provides the chart context, sizing, brush, transform, and tooltip plumbing — but skips `<ChartChildren>` and the `Layer` / `Axis` / `Grid` / `Rule` / `Highlight` / `ChartClipPath` import chain it pulls in. |
| 70 | + |
| 71 | + Use it for geo maps, custom layouts, or any chart that renders its own primitives directly via the `children` snippet: |
| 72 | + |
| 73 | + ```svelte |
| 74 | + <script> |
| 75 | + import { ChartCore, Svg, GeoProjection, GeoPath } from 'layerchart/svg'; |
| 76 | + </script> |
| 77 | +
|
| 78 | + <ChartCore data={countries}> |
| 79 | + {#snippet children({ context })} |
| 80 | + <Svg> |
| 81 | + <GeoProjection projection={geoMercator} fitGeojson={countries}> |
| 82 | + <GeoPath geojson={countries} fill="steelblue" /> |
| 83 | + </GeoProjection> |
| 84 | + </Svg> |
| 85 | + {/snippet} |
| 86 | + </ChartCore> |
| 87 | + ``` |
| 88 | + |
| 89 | + Measured savings (bundle scenarios): |
| 90 | + - `base` (`<Chart>`) → `core` (`<ChartCore>`): 83.42 → 50.93 KB gz (**−39%**) |
| 91 | + - `geo` (`<Chart>` + `GeoPath`/`GeoPoint`) → `core-geo` (`<ChartCore>` + `GeoProjection` + `GeoPath`): 87.23 → 54.67 KB gz (**−37%**) |
| 92 | + - `base-svg` (per-layer) → `core-svg` (per-layer): 77.37 → 50.88 KB gz (**−34%**) |
| 93 | + |
| 94 | + ### Behavior |
| 95 | + |
| 96 | + Identical to the agnostic versions: visual output, props, types, and bindable refs all match. The dispatcher pattern adds ~0.2 KB per primitive to `core` for users on the agnostic API (transitive cost from `Highlight` / `Axis` / `Chart`) — a worthwhile tradeoff for the opt-in per-layer savings. |
| 97 | + |
| 98 | + See the updated ["Bundle Size" guide](https://layerchart.com/docs/guides/bundle-size) for the full table, tradeoffs, and when to opt into per-layer imports. |
| 99 | + |
3 | 100 | ## 2.0.0-next.60 |
4 | 101 |
|
5 | 102 | ### Minor Changes |
|
0 commit comments