@semilayer/charts
v0.1.8
Published
Vanilla TypeScript chart library for SemiLayer analyze results — zero framework deps, SVG-rendered, themed, animated, exportable, live-updatable
Maintainers
Readme
Install
pnpm add @semilayer/chartsQuick start
import { createChart } from '@semilayer/charts'
import { beam } from './generated/beam'
const chart = createChart(document.querySelector('#tile')!, {
shape: 'line',
source: {
kind: 'beam',
beam: beam.recipes.analyze.publishedByDay,
input: { where: { status: 'published' } },
liveUpdates: true,
},
encoding: { xField: 'day', yField: 'count', seriesField: 'cuisine' },
})
chart.onBucketClick((bucketKey, bucket) => {
// open a drill-down panel using analyze.publishedByDay.rows({ bucketKey })
})Shapes
table, line, area, stackedArea, bar, stackedBar, scatter, pie, donut, heatmap, geo, funnel, cohort, treemap, radar — one file per shape under src/shapes/, tree-shakeable. Pick whatever fits the data; the library does not opinion-load.
Sources
createChart accepts four source kinds — pick the one that matches how your app already moves data:
| kind | When to use |
|---|---|
| data | You already have an AnalyzeResult. Caller owns fetching + cache. |
| beam | Codegen-emitted handle + input. Chart fetches + (optionally) subscribes for live updates. |
| http | Plain GET/POST against an analyze URL. Optional pollMs for refresh. |
| ws | Pre-existing WebSocket. Chart sends analyze.subscribe and applies snapshot/diff/tick frames. |
Theming
lightTheme and darkTheme ship pre-baked with the SemiLayer brand gradient (#8B5CF6 → #3B82F6 → #10B981). Apps already driving theming via CSS variables can bridge:
import { themeFromCssVars, lightTheme } from '@semilayer/charts'
const theme = themeFromCssVars(host, {
foreground: '--text-primary',
background: '--surface',
palette: ['--brand-1', '--brand-2', '--brand-3'],
}, lightTheme)prefers-reduced-motion: reduce is honored — animations snap to their final state instead of tweening.
Exports
Every chart instance ships:
chart.exportCSV() // string — one row per bucket
chart.exportJSON() // string — same shape as AnalyzeResult
chart.exportSVG() // string — standalone SVG markup
chart.exportPNG() // Promise<string> — PNG data URL via canvasCustom Element
Opt-in import for HTML-first apps:
<script type="module">
import { registerSemiLayerChartElement } from '@semilayer/charts/element'
registerSemiLayerChartElement()
</script>
<sl-chart shape="line" data='{"kind":"metric","buckets":[…]}' encoding='{"xField":"day"}'></sl-chart>Headless
Pure-function shape primitives are available at @semilayer/charts/headless (re-exported from @semilayer/headless) so you can drive your own renderer:
import { toLineSeries } from '@semilayer/charts/headless'See Also
- Analyze facet docs
@semilayer/headless— the canonical home of the math primitives@semilayer/react-charts— React wrapper around this package
License
MIT
