@faintshadow/flarecharts 26.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +40 -0
- package/README.md +103 -0
- package/dist/charts/AreaChart.svelte +150 -0
- package/dist/charts/AreaChart.svelte.d.ts +60 -0
- package/dist/charts/BarChart.svelte +142 -0
- package/dist/charts/BarChart.svelte.d.ts +58 -0
- package/dist/charts/BoxPlotChart.svelte +138 -0
- package/dist/charts/BoxPlotChart.svelte.d.ts +56 -0
- package/dist/charts/DonutChart.svelte +129 -0
- package/dist/charts/DonutChart.svelte.d.ts +73 -0
- package/dist/charts/LineChart.svelte +149 -0
- package/dist/charts/LineChart.svelte.d.ts +63 -0
- package/dist/charts/Sparkline.svelte +87 -0
- package/dist/charts/Sparkline.svelte.d.ts +40 -0
- package/dist/charts/StackChart.svelte +157 -0
- package/dist/charts/StackChart.svelte.d.ts +69 -0
- package/dist/components/Arc.svelte +202 -0
- package/dist/components/Arc.svelte.d.ts +50 -0
- package/dist/components/Area.svelte +264 -0
- package/dist/components/Area.svelte.d.ts +54 -0
- package/dist/components/Axis.svelte +139 -0
- package/dist/components/Axis.svelte.d.ts +26 -0
- package/dist/components/Bars.svelte +192 -0
- package/dist/components/Bars.svelte.d.ts +55 -0
- package/dist/components/Box.svelte +287 -0
- package/dist/components/Box.svelte.d.ts +48 -0
- package/dist/components/Chart.svelte +207 -0
- package/dist/components/Chart.svelte.d.ts +23 -0
- package/dist/components/Crosshair.svelte +67 -0
- package/dist/components/Crosshair.svelte.d.ts +14 -0
- package/dist/components/Grid.svelte +38 -0
- package/dist/components/Grid.svelte.d.ts +14 -0
- package/dist/components/Labels.svelte +61 -0
- package/dist/components/Labels.svelte.d.ts +35 -0
- package/dist/components/Legend.svelte +81 -0
- package/dist/components/Legend.svelte.d.ts +12 -0
- package/dist/components/Line.svelte +192 -0
- package/dist/components/Line.svelte.d.ts +47 -0
- package/dist/components/PlotBand.svelte +68 -0
- package/dist/components/PlotBand.svelte.d.ts +14 -0
- package/dist/components/PlotLine.svelte +54 -0
- package/dist/components/PlotLine.svelte.d.ts +16 -0
- package/dist/components/Points.svelte +179 -0
- package/dist/components/Points.svelte.d.ts +53 -0
- package/dist/components/Svg.svelte +36 -0
- package/dist/components/Svg.svelte.d.ts +8 -0
- package/dist/components/Tooltip.svelte +211 -0
- package/dist/components/Tooltip.svelte.d.ts +44 -0
- package/dist/core/bisect.d.ts +5 -0
- package/dist/core/bisect.js +23 -0
- package/dist/core/context.svelte.d.ts +140 -0
- package/dist/core/context.svelte.js +294 -0
- package/dist/core/curves.d.ts +4 -0
- package/dist/core/curves.js +13 -0
- package/dist/core/hit.d.ts +34 -0
- package/dist/core/hit.js +43 -0
- package/dist/core/keynav.d.ts +20 -0
- package/dist/core/keynav.js +41 -0
- package/dist/core/labels.d.ts +39 -0
- package/dist/core/labels.js +27 -0
- package/dist/core/merge.d.ts +17 -0
- package/dist/core/merge.js +46 -0
- package/dist/core/motion.svelte.d.ts +31 -0
- package/dist/core/motion.svelte.js +129 -0
- package/dist/core/normalize.d.ts +35 -0
- package/dist/core/normalize.js +97 -0
- package/dist/core/options.d.ts +113 -0
- package/dist/core/options.js +36 -0
- package/dist/core/palette.d.ts +8 -0
- package/dist/core/palette.js +24 -0
- package/dist/core/responsive.d.ts +6 -0
- package/dist/core/responsive.js +19 -0
- package/dist/core/scales.d.ts +31 -0
- package/dist/core/scales.js +89 -0
- package/dist/core/stack.d.ts +19 -0
- package/dist/core/stack.js +133 -0
- package/dist/core/stats.d.ts +45 -0
- package/dist/core/stats.js +114 -0
- package/dist/core/symbols.d.ts +8 -0
- package/dist/core/symbols.js +31 -0
- package/dist/core/types.d.ts +28 -0
- package/dist/core/types.js +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +42 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
FlareCharts License (MIT with Attribution)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Safwen TBINI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person or organization
|
|
6
|
+
obtaining a copy of this software and associated documentation files
|
|
7
|
+
("FlareCharts", the "Software"), to deal in the Software without restriction,
|
|
8
|
+
including without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
10
|
+
persons to whom the Software is furnished to do so, subject to the following
|
|
11
|
+
conditions:
|
|
12
|
+
|
|
13
|
+
1. The above copyright notice and this permission notice shall be included in
|
|
14
|
+
all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
2. Attribution. Any application, product, or distribution that uses the
|
|
17
|
+
Software, in whole or in part, must include a visible credit to FlareCharts
|
|
18
|
+
in a place accessible to end users (for example: an "About" page, a credits
|
|
19
|
+
or settings screen, documentation, or a page footer). The credit must show
|
|
20
|
+
the project name and a link to the project repository — either as a
|
|
21
|
+
clickable hyperlink or as plain, copyable text — for example:
|
|
22
|
+
|
|
23
|
+
FlareCharts can be found here: https://gitlab.com/FaintShadow/flarecharts
|
|
24
|
+
|
|
25
|
+
The repository URL is the one specified in the NOTICE file of the version
|
|
26
|
+
of the Software in use.
|
|
27
|
+
|
|
28
|
+
No commercial license is offered at this time. One may be made available in
|
|
29
|
+
a future version of the Software. A commercial license, when offered, removes
|
|
30
|
+
the attribution requirement of this condition 2, and the terms accompanying
|
|
31
|
+
that version apply instead. Until then, this condition 2 applies to all use,
|
|
32
|
+
including commercial use.
|
|
33
|
+
|
|
34
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
35
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
36
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
37
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
38
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
39
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<p align="center"><img src="https://gitlab.com/FaintShadow/flarecharts/-/raw/main/static/favicon.svg" width="127" alt="Flarecharts Logo"></p>
|
|
2
|
+
|
|
3
|
+
## About Flarecharts
|
|
4
|
+
|
|
5
|
+
Flarecharts is a composable SVG chart library for **Svelte 5** built on runes. We believe data visualization should be expressive, accessible, and easy to customize. Flarecharts takes the pain out of charting by easing common tasks used in many web projects, such as:
|
|
6
|
+
|
|
7
|
+
- **Runes-first architecture:** Built specifically for Svelte 5.
|
|
8
|
+
- **d3 for math only:** No d3 DOM bindings, just pure SVG components.
|
|
9
|
+
- **CSS-variable themed:** "Styled mode" is the only mode. Theme by setting variables on any wrapper.
|
|
10
|
+
- **Composable Primitives & one-tag Charts:** Eject from a wrapper to custom composition without reshaping your data.
|
|
11
|
+
- **Accessibility built-in:** Visually-hidden data tables, aria-live regions, and full arrow-key point navigation.
|
|
12
|
+
- **First-class stacking & curves:** Modelled on d3's stack generator with diverging, stream, and silhouette offsets.
|
|
13
|
+
|
|
14
|
+
## Learning Flarecharts
|
|
15
|
+
|
|
16
|
+
Flarecharts has extensive and thorough [documentation](https://flarecharts.gitbook.io/docs). It covers everything from getting started to deep dives on stacking, curves, and accessibility.
|
|
17
|
+
|
|
18
|
+
The documentation is also available in [docs/](https://gitlab.com/FaintShadow/flarecharts/-/tree/main/docs) directory of the repository, covering:
|
|
19
|
+
|
|
20
|
+
- **Core Concepts** — the two layers, data, scales & axes, options & precedence
|
|
21
|
+
- **Theming** — full variable surface and class lists for plain-CSS/Tailwind restyling
|
|
22
|
+
- **Charts** — LineChart, AreaChart, BarChart, StackChart, DonutChart, Sparkline
|
|
23
|
+
- **Primitives** — Chart/Svg, marks, axes & grid, overlays
|
|
24
|
+
- **Guides** — stacking, curves, accessibility, responsive, interaction, etc..
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Install Flarecharts via your preferred package manager:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @faintshadow/flarecharts
|
|
32
|
+
# or
|
|
33
|
+
bun add @faintshadow/flarecharts
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## One Tag or Composed — Your Choice
|
|
37
|
+
|
|
38
|
+
Use a single `<LineChart>` tag for quick implementation:
|
|
39
|
+
|
|
40
|
+
```svelte
|
|
41
|
+
<LineChart
|
|
42
|
+
xAxis={{ type: 'time' }}
|
|
43
|
+
series={[
|
|
44
|
+
{ name: 'Revenue', data: revenue, x: (d) => d.date, y: (d) => d.value },
|
|
45
|
+
{ name: 'Costs', data: costs, x: (d) => d.date, y: (d) => d.value }
|
|
46
|
+
]}
|
|
47
|
+
bands={[{ from: 55, to: 70, label: 'Target' }]}
|
|
48
|
+
crosshair
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or compose your own chart pixel-identically using primitives, using the exact same data shapes and defaults. When you outgrow the one-tag form, you don't have to rewrite anything:
|
|
53
|
+
|
|
54
|
+
```svelte
|
|
55
|
+
<script lang="ts">
|
|
56
|
+
import { Chart, Svg, Axis, Grid, Line, PlotBand } from 'flarechart';
|
|
57
|
+
|
|
58
|
+
const revenue = [
|
|
59
|
+
{ date: new Date(2025, 0, 1), value: 48 },
|
|
60
|
+
{ date: new Date(2025, 1, 1), value: 61 }
|
|
61
|
+
// ...
|
|
62
|
+
];
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<div style="height: 280px">
|
|
66
|
+
<Chart x={{ type: 'time' }} label="Revenue by month">
|
|
67
|
+
<Svg>
|
|
68
|
+
<Grid y />
|
|
69
|
+
<PlotBand from={55} to={70} label="Target" />
|
|
70
|
+
<Line data={revenue} x={(d) => d.date} y={(d) => d.value} />
|
|
71
|
+
<Axis placement="left" />
|
|
72
|
+
<Axis placement="bottom" />
|
|
73
|
+
</Svg>
|
|
74
|
+
</Chart>
|
|
75
|
+
</div>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The chart fills its container (give it a height) and resizes with it. Paint order is markup order.
|
|
79
|
+
|
|
80
|
+
## Core Concepts
|
|
81
|
+
|
|
82
|
+
- **Two Layers:** **Primitives** (`src/lib/components/`) are composable building blocks you assemble in markup. **Charts** (`src/lib/charts/`) are one-tag wrappers built *only* from Primitives.
|
|
83
|
+
- **Flexible Data Shapes:** Every mark accepts the same `data` shapes (`number[]`, `[x, y][]`, `{ x?, y }[]`, or `T[]` with accessors). `null` / `NaN` values render as gaps, never zeros.
|
|
84
|
+
- **Theming:** Every visual attribute resolves from a CSS custom property with a built-in fallback. Dark mode is just you flipping variables — the library does nothing, by design.
|
|
85
|
+
- **Accessibility:** `<Chart>` renders a `role="group"` container with an aria-label, a visually-hidden data table of every visible series, and arrow-key point navigation.
|
|
86
|
+
|
|
87
|
+
## Development
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
bun install
|
|
91
|
+
bun run dev # demo app (routes/)
|
|
92
|
+
bun run test # vitest: normalizer, merge, scales, stacking, …
|
|
93
|
+
bun run check # svelte-check, strict
|
|
94
|
+
bun run package # svelte-package + publint
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Contributing
|
|
98
|
+
|
|
99
|
+
Thank you for considering contributing to Flarecharts! Please review the design rationale in the [Architecture](https://flarecharts.gitbook.io/docs/contributing/architecture) page before opening a pull request.
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
Flarecharts is open-sourced software licensed under the [MIT + Attribution License](https://gitlab.com/FaintShadow/flarecharts/-/blob/main/LICENSE).
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import Chart from '../components/Chart.svelte';
|
|
3
|
+
import Svg from '../components/Svg.svelte';
|
|
4
|
+
import Axis from '../components/Axis.svelte';
|
|
5
|
+
import Grid from '../components/Grid.svelte';
|
|
6
|
+
import Area from '../components/Area.svelte';
|
|
7
|
+
|
|
8
|
+
import Labels from '../components/Labels.svelte';
|
|
9
|
+
import PlotBand from '../components/PlotBand.svelte';
|
|
10
|
+
import PlotLine from '../components/PlotLine.svelte';
|
|
11
|
+
import Tooltip from '../components/Tooltip.svelte';
|
|
12
|
+
import Crosshair from '../components/Crosshair.svelte';
|
|
13
|
+
import Legend from '../components/Legend.svelte';
|
|
14
|
+
import { resolveSeries, splitAxisOptions } from '../core/options.js';
|
|
15
|
+
import type {
|
|
16
|
+
BandSpec,
|
|
17
|
+
LegendSpec,
|
|
18
|
+
PlotLineSpec,
|
|
19
|
+
PlotOptions,
|
|
20
|
+
SeriesOptions,
|
|
21
|
+
SimpleAxisOptions,
|
|
22
|
+
TooltipSpec
|
|
23
|
+
} from '../core/options.js';
|
|
24
|
+
import { applyResponsive } from '../core/responsive.js';
|
|
25
|
+
import type { ResponsiveRule } from '../core/responsive.js';
|
|
26
|
+
import type { Padding } from '../core/types.js';
|
|
27
|
+
|
|
28
|
+
interface BaseProps {
|
|
29
|
+
series: SeriesOptions<T>[];
|
|
30
|
+
xAxis?: SimpleAxisOptions;
|
|
31
|
+
yAxis?: SimpleAxisOptions;
|
|
32
|
+
bands?: BandSpec[];
|
|
33
|
+
lines?: PlotLineSpec[];
|
|
34
|
+
grid?: boolean;
|
|
35
|
+
crosshair?: boolean;
|
|
36
|
+
tooltip?: boolean | TooltipSpec;
|
|
37
|
+
legend?: boolean | LegendSpec;
|
|
38
|
+
plotOptions?: PlotOptions<T>;
|
|
39
|
+
padding?: Padding;
|
|
40
|
+
label?: string;
|
|
41
|
+
/** Accessible chart description. */
|
|
42
|
+
description?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface Props extends BaseProps {
|
|
46
|
+
responsive?: ResponsiveRule<BaseProps>[];
|
|
47
|
+
class?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let {
|
|
51
|
+
series,
|
|
52
|
+
xAxis,
|
|
53
|
+
yAxis,
|
|
54
|
+
bands,
|
|
55
|
+
lines,
|
|
56
|
+
grid = true,
|
|
57
|
+
crosshair = false,
|
|
58
|
+
tooltip = true,
|
|
59
|
+
legend,
|
|
60
|
+
plotOptions,
|
|
61
|
+
padding,
|
|
62
|
+
label = 'Area chart',
|
|
63
|
+
description,
|
|
64
|
+
responsive,
|
|
65
|
+
class: klass = ''
|
|
66
|
+
}: Props = $props();
|
|
67
|
+
|
|
68
|
+
let width = $state(0);
|
|
69
|
+
|
|
70
|
+
const eff = $derived(
|
|
71
|
+
applyResponsive(
|
|
72
|
+
{ series, xAxis, yAxis, bands, lines, grid, crosshair, tooltip, legend, plotOptions, padding, label, description },
|
|
73
|
+
responsive,
|
|
74
|
+
width
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const resolved = $derived(eff.series.map((s) => resolveSeries(eff.plotOptions, s)));
|
|
79
|
+
const xa = $derived(splitAxisOptions(eff.xAxis));
|
|
80
|
+
const ya = $derived(splitAxisOptions(eff.yAxis));
|
|
81
|
+
|
|
82
|
+
const legendOn = $derived(
|
|
83
|
+
eff.legend === undefined ? eff.series.length > 1 : eff.legend !== false
|
|
84
|
+
);
|
|
85
|
+
const legendPos = $derived(
|
|
86
|
+
typeof eff.legend === 'object' && eff.legend ? (eff.legend.position ?? 'bottom') : 'bottom'
|
|
87
|
+
);
|
|
88
|
+
const tooltipOn = $derived(eff.tooltip !== false);
|
|
89
|
+
const tip = $derived(typeof eff.tooltip === 'object' && eff.tooltip ? eff.tooltip : {});
|
|
90
|
+
const pad = $derived({
|
|
91
|
+
...(legendOn ? (legendPos === 'top' ? { top: 48 } : { bottom: 56 }) : {}),
|
|
92
|
+
...eff.padding
|
|
93
|
+
});
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<div class="fc-simple fc-area-chart {klass}" bind:clientWidth={width}>
|
|
97
|
+
<Chart x={xa.scale} y={ya.scale} padding={pad} label={eff.label} description={eff.description}>
|
|
98
|
+
<Svg>
|
|
99
|
+
{#if eff.grid}<Grid y />{/if}
|
|
100
|
+
{#each eff.bands ?? [] as band, i (i)}
|
|
101
|
+
<PlotBand axis={band.axis} from={band.from} to={band.to} color={band.color} label={band.label} />
|
|
102
|
+
{/each}
|
|
103
|
+
{#each eff.lines ?? [] as pl, i (i)}
|
|
104
|
+
<PlotLine axis={pl.axis} value={pl.value} color={pl.color} dash={pl.dash} label={pl.label} />
|
|
105
|
+
{/each}
|
|
106
|
+
{#if eff.crosshair}<Crosshair />{/if}
|
|
107
|
+
{#each resolved as s, i (i)}
|
|
108
|
+
<Area
|
|
109
|
+
data={s.data}
|
|
110
|
+
x={s.x}
|
|
111
|
+
y={s.y}
|
|
112
|
+
color={s.color}
|
|
113
|
+
name={s.name}
|
|
114
|
+
description={s.description}
|
|
115
|
+
curve={s.curve}
|
|
116
|
+
strokeWidth={s.strokeWidth}
|
|
117
|
+
fillOpacity={s.fillOpacity}
|
|
118
|
+
stacking={s.stacking}
|
|
119
|
+
stack={s.stack}
|
|
120
|
+
index={i}
|
|
121
|
+
markers={s.markers}
|
|
122
|
+
symbol={s.symbol}
|
|
123
|
+
symbolSize={s.symbolSize}
|
|
124
|
+
/>
|
|
125
|
+
{/each}
|
|
126
|
+
{#each resolved as s, i (i)}
|
|
127
|
+
{#if s.labels}
|
|
128
|
+
<Labels data={s.data} x={s.x} y={s.y} />
|
|
129
|
+
{/if}
|
|
130
|
+
{/each}
|
|
131
|
+
{#if xa.visible}
|
|
132
|
+
<Axis placement="bottom" title={xa.display.title} ticks={xa.display.ticks} format={xa.display.format} rotate={xa.display.rotate} />
|
|
133
|
+
{/if}
|
|
134
|
+
{#if ya.visible}
|
|
135
|
+
<Axis placement="left" title={ya.display.title} ticks={ya.display.ticks} format={ya.display.format} rotate={ya.display.rotate} />
|
|
136
|
+
{/if}
|
|
137
|
+
</Svg>
|
|
138
|
+
{#if tooltipOn}
|
|
139
|
+
<Tooltip mode={tip.mode ?? 'bisect-x'} shared={tip.shared ?? true} formatX={tip.formatX} formatY={tip.formatY} />
|
|
140
|
+
{/if}
|
|
141
|
+
{#if legendOn}<Legend position={legendPos} />{/if}
|
|
142
|
+
</Chart>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<style>
|
|
146
|
+
.fc-simple {
|
|
147
|
+
width: 100%;
|
|
148
|
+
height: 100%;
|
|
149
|
+
}
|
|
150
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { BandSpec, LegendSpec, PlotLineSpec, PlotOptions, SeriesOptions, SimpleAxisOptions, TooltipSpec } from '../core/options.js';
|
|
2
|
+
import type { ResponsiveRule } from '../core/responsive.js';
|
|
3
|
+
import type { Padding } from '../core/types.js';
|
|
4
|
+
declare function $$render<T>(): {
|
|
5
|
+
props: {
|
|
6
|
+
series: SeriesOptions<T>[];
|
|
7
|
+
xAxis?: SimpleAxisOptions;
|
|
8
|
+
yAxis?: SimpleAxisOptions;
|
|
9
|
+
bands?: BandSpec[];
|
|
10
|
+
lines?: PlotLineSpec[];
|
|
11
|
+
grid?: boolean;
|
|
12
|
+
crosshair?: boolean;
|
|
13
|
+
tooltip?: boolean | TooltipSpec;
|
|
14
|
+
legend?: boolean | LegendSpec;
|
|
15
|
+
plotOptions?: PlotOptions<T>;
|
|
16
|
+
padding?: Padding;
|
|
17
|
+
label?: string;
|
|
18
|
+
/** Accessible chart description. */
|
|
19
|
+
description?: string;
|
|
20
|
+
} & {
|
|
21
|
+
responsive?: ResponsiveRule<{
|
|
22
|
+
series: SeriesOptions<T>[];
|
|
23
|
+
xAxis?: SimpleAxisOptions;
|
|
24
|
+
yAxis?: SimpleAxisOptions;
|
|
25
|
+
bands?: BandSpec[];
|
|
26
|
+
lines?: PlotLineSpec[];
|
|
27
|
+
grid?: boolean;
|
|
28
|
+
crosshair?: boolean;
|
|
29
|
+
tooltip?: boolean | TooltipSpec;
|
|
30
|
+
legend?: boolean | LegendSpec;
|
|
31
|
+
plotOptions?: PlotOptions<T>;
|
|
32
|
+
padding?: Padding;
|
|
33
|
+
label?: string;
|
|
34
|
+
/** Accessible chart description. */
|
|
35
|
+
description?: string;
|
|
36
|
+
}>[];
|
|
37
|
+
class?: string;
|
|
38
|
+
};
|
|
39
|
+
exports: {};
|
|
40
|
+
bindings: "";
|
|
41
|
+
slots: {};
|
|
42
|
+
events: {};
|
|
43
|
+
};
|
|
44
|
+
declare class __sveltets_Render<T> {
|
|
45
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
46
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
47
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
48
|
+
bindings(): "";
|
|
49
|
+
exports(): {};
|
|
50
|
+
}
|
|
51
|
+
interface $$IsomorphicComponent {
|
|
52
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
53
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
54
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
55
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
56
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
57
|
+
}
|
|
58
|
+
declare const AreaChart: $$IsomorphicComponent;
|
|
59
|
+
type AreaChart<T> = InstanceType<typeof AreaChart<T>>;
|
|
60
|
+
export default AreaChart;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import Chart from '../components/Chart.svelte';
|
|
3
|
+
import Svg from '../components/Svg.svelte';
|
|
4
|
+
import Axis from '../components/Axis.svelte';
|
|
5
|
+
import Grid from '../components/Grid.svelte';
|
|
6
|
+
import Bars from '../components/Bars.svelte';
|
|
7
|
+
import Labels from '../components/Labels.svelte';
|
|
8
|
+
import PlotBand from '../components/PlotBand.svelte';
|
|
9
|
+
import PlotLine from '../components/PlotLine.svelte';
|
|
10
|
+
import Tooltip from '../components/Tooltip.svelte';
|
|
11
|
+
import Legend from '../components/Legend.svelte';
|
|
12
|
+
import { resolveSeries, splitAxisOptions } from '../core/options.js';
|
|
13
|
+
import type {
|
|
14
|
+
BandSpec,
|
|
15
|
+
LegendSpec,
|
|
16
|
+
PlotLineSpec,
|
|
17
|
+
PlotOptions,
|
|
18
|
+
SeriesOptions,
|
|
19
|
+
SimpleAxisOptions,
|
|
20
|
+
TooltipSpec
|
|
21
|
+
} from '../core/options.js';
|
|
22
|
+
import { applyResponsive } from '../core/responsive.js';
|
|
23
|
+
import type { ResponsiveRule } from '../core/responsive.js';
|
|
24
|
+
import type { Padding } from '../core/types.js';
|
|
25
|
+
|
|
26
|
+
interface BaseProps {
|
|
27
|
+
series: SeriesOptions<T>[];
|
|
28
|
+
xAxis?: SimpleAxisOptions;
|
|
29
|
+
yAxis?: SimpleAxisOptions;
|
|
30
|
+
bands?: BandSpec[];
|
|
31
|
+
lines?: PlotLineSpec[];
|
|
32
|
+
grid?: boolean;
|
|
33
|
+
tooltip?: boolean | TooltipSpec;
|
|
34
|
+
legend?: boolean | LegendSpec;
|
|
35
|
+
plotOptions?: PlotOptions<T>;
|
|
36
|
+
padding?: Padding;
|
|
37
|
+
label?: string;
|
|
38
|
+
/** Accessible chart description. */
|
|
39
|
+
description?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface Props extends BaseProps {
|
|
43
|
+
responsive?: ResponsiveRule<BaseProps>[];
|
|
44
|
+
class?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let {
|
|
48
|
+
series,
|
|
49
|
+
xAxis,
|
|
50
|
+
yAxis,
|
|
51
|
+
bands,
|
|
52
|
+
lines,
|
|
53
|
+
grid = true,
|
|
54
|
+
tooltip = true,
|
|
55
|
+
legend,
|
|
56
|
+
plotOptions,
|
|
57
|
+
padding,
|
|
58
|
+
label = 'Bar chart',
|
|
59
|
+
description,
|
|
60
|
+
responsive,
|
|
61
|
+
class: klass = ''
|
|
62
|
+
}: Props = $props();
|
|
63
|
+
|
|
64
|
+
let width = $state(0);
|
|
65
|
+
|
|
66
|
+
const eff = $derived(
|
|
67
|
+
applyResponsive(
|
|
68
|
+
{ series, xAxis, yAxis, bands, lines, grid, tooltip, legend, plotOptions, padding, label, description },
|
|
69
|
+
responsive,
|
|
70
|
+
width
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const resolved = $derived(eff.series.map((s) => resolveSeries(eff.plotOptions, s)));
|
|
75
|
+
const xa = $derived(splitAxisOptions(eff.xAxis));
|
|
76
|
+
const ya = $derived(splitAxisOptions(eff.yAxis));
|
|
77
|
+
|
|
78
|
+
const legendOn = $derived(
|
|
79
|
+
eff.legend === undefined ? eff.series.length > 1 : eff.legend !== false
|
|
80
|
+
);
|
|
81
|
+
const legendPos = $derived(
|
|
82
|
+
typeof eff.legend === 'object' && eff.legend ? (eff.legend.position ?? 'bottom') : 'bottom'
|
|
83
|
+
);
|
|
84
|
+
const tooltipOn = $derived(eff.tooltip !== false);
|
|
85
|
+
const tip = $derived(typeof eff.tooltip === 'object' && eff.tooltip ? eff.tooltip : {});
|
|
86
|
+
const pad = $derived({
|
|
87
|
+
...(legendOn ? (legendPos === 'top' ? { top: 48 } : { bottom: 56 }) : {}),
|
|
88
|
+
...eff.padding
|
|
89
|
+
});
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<div class="fc-simple fc-bar-chart {klass}" bind:clientWidth={width}>
|
|
93
|
+
<Chart x={xa.scale} y={ya.scale} padding={pad} label={eff.label} description={eff.description}>
|
|
94
|
+
<Svg>
|
|
95
|
+
{#if eff.grid}<Grid y />{/if}
|
|
96
|
+
{#each eff.bands ?? [] as band, i (i)}
|
|
97
|
+
<PlotBand axis={band.axis} from={band.from} to={band.to} color={band.color} label={band.label} />
|
|
98
|
+
{/each}
|
|
99
|
+
{#each resolved as s, i (i)}
|
|
100
|
+
<Bars
|
|
101
|
+
data={s.data}
|
|
102
|
+
x={s.x}
|
|
103
|
+
y={s.y}
|
|
104
|
+
color={s.color}
|
|
105
|
+
colorFor={s.colorFor}
|
|
106
|
+
name={s.name}
|
|
107
|
+
description={s.description}
|
|
108
|
+
stacking={s.stacking}
|
|
109
|
+
stack={s.stack}
|
|
110
|
+
barPadding={s.barPadding}
|
|
111
|
+
rx={s.rx}
|
|
112
|
+
index={i}
|
|
113
|
+
/>
|
|
114
|
+
{/each}
|
|
115
|
+
{#each eff.lines ?? [] as pl, i (i)}
|
|
116
|
+
<PlotLine axis={pl.axis} value={pl.value} color={pl.color} dash={pl.dash} label={pl.label} />
|
|
117
|
+
{/each}
|
|
118
|
+
{#each resolved as s, i (i)}
|
|
119
|
+
{#if s.labels}
|
|
120
|
+
<Labels data={s.data} x={s.x} y={s.y} />
|
|
121
|
+
{/if}
|
|
122
|
+
{/each}
|
|
123
|
+
{#if xa.visible}
|
|
124
|
+
<Axis placement="bottom" title={xa.display.title} ticks={xa.display.ticks} format={xa.display.format} rotate={xa.display.rotate} />
|
|
125
|
+
{/if}
|
|
126
|
+
{#if ya.visible}
|
|
127
|
+
<Axis placement="left" title={ya.display.title} ticks={ya.display.ticks} format={ya.display.format} rotate={ya.display.rotate} />
|
|
128
|
+
{/if}
|
|
129
|
+
</Svg>
|
|
130
|
+
{#if tooltipOn}
|
|
131
|
+
<Tooltip mode={tip.mode ?? 'band'} shared={tip.shared ?? true} formatX={tip.formatX} formatY={tip.formatY} />
|
|
132
|
+
{/if}
|
|
133
|
+
{#if legendOn}<Legend position={legendPos} />{/if}
|
|
134
|
+
</Chart>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<style>
|
|
138
|
+
.fc-simple {
|
|
139
|
+
width: 100%;
|
|
140
|
+
height: 100%;
|
|
141
|
+
}
|
|
142
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { BandSpec, LegendSpec, PlotLineSpec, PlotOptions, SeriesOptions, SimpleAxisOptions, TooltipSpec } from '../core/options.js';
|
|
2
|
+
import type { ResponsiveRule } from '../core/responsive.js';
|
|
3
|
+
import type { Padding } from '../core/types.js';
|
|
4
|
+
declare function $$render<T>(): {
|
|
5
|
+
props: {
|
|
6
|
+
series: SeriesOptions<T>[];
|
|
7
|
+
xAxis?: SimpleAxisOptions;
|
|
8
|
+
yAxis?: SimpleAxisOptions;
|
|
9
|
+
bands?: BandSpec[];
|
|
10
|
+
lines?: PlotLineSpec[];
|
|
11
|
+
grid?: boolean;
|
|
12
|
+
tooltip?: boolean | TooltipSpec;
|
|
13
|
+
legend?: boolean | LegendSpec;
|
|
14
|
+
plotOptions?: PlotOptions<T>;
|
|
15
|
+
padding?: Padding;
|
|
16
|
+
label?: string;
|
|
17
|
+
/** Accessible chart description. */
|
|
18
|
+
description?: string;
|
|
19
|
+
} & {
|
|
20
|
+
responsive?: ResponsiveRule<{
|
|
21
|
+
series: SeriesOptions<T>[];
|
|
22
|
+
xAxis?: SimpleAxisOptions;
|
|
23
|
+
yAxis?: SimpleAxisOptions;
|
|
24
|
+
bands?: BandSpec[];
|
|
25
|
+
lines?: PlotLineSpec[];
|
|
26
|
+
grid?: boolean;
|
|
27
|
+
tooltip?: boolean | TooltipSpec;
|
|
28
|
+
legend?: boolean | LegendSpec;
|
|
29
|
+
plotOptions?: PlotOptions<T>;
|
|
30
|
+
padding?: Padding;
|
|
31
|
+
label?: string;
|
|
32
|
+
/** Accessible chart description. */
|
|
33
|
+
description?: string;
|
|
34
|
+
}>[];
|
|
35
|
+
class?: string;
|
|
36
|
+
};
|
|
37
|
+
exports: {};
|
|
38
|
+
bindings: "";
|
|
39
|
+
slots: {};
|
|
40
|
+
events: {};
|
|
41
|
+
};
|
|
42
|
+
declare class __sveltets_Render<T> {
|
|
43
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
44
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
45
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
46
|
+
bindings(): "";
|
|
47
|
+
exports(): {};
|
|
48
|
+
}
|
|
49
|
+
interface $$IsomorphicComponent {
|
|
50
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
51
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
52
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
53
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
54
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
55
|
+
}
|
|
56
|
+
declare const BarChart: $$IsomorphicComponent;
|
|
57
|
+
type BarChart<T> = InstanceType<typeof BarChart<T>>;
|
|
58
|
+
export default BarChart;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import Chart from '../components/Chart.svelte';
|
|
3
|
+
import Svg from '../components/Svg.svelte';
|
|
4
|
+
import Axis from '../components/Axis.svelte';
|
|
5
|
+
import Grid from '../components/Grid.svelte';
|
|
6
|
+
import Box from '../components/Box.svelte';
|
|
7
|
+
import PlotBand from '../components/PlotBand.svelte';
|
|
8
|
+
import PlotLine from '../components/PlotLine.svelte';
|
|
9
|
+
import Tooltip from '../components/Tooltip.svelte';
|
|
10
|
+
import Legend from '../components/Legend.svelte';
|
|
11
|
+
import { resolveSeries, splitAxisOptions } from '../core/options.js';
|
|
12
|
+
import type {
|
|
13
|
+
BandSpec,
|
|
14
|
+
LegendSpec,
|
|
15
|
+
PlotLineSpec,
|
|
16
|
+
PlotOptions,
|
|
17
|
+
SeriesOptions,
|
|
18
|
+
SimpleAxisOptions,
|
|
19
|
+
TooltipSpec
|
|
20
|
+
} from '../core/options.js';
|
|
21
|
+
import { applyResponsive } from '../core/responsive.js';
|
|
22
|
+
import type { ResponsiveRule } from '../core/responsive.js';
|
|
23
|
+
import type { Padding } from '../core/types.js';
|
|
24
|
+
|
|
25
|
+
interface BaseProps {
|
|
26
|
+
series: SeriesOptions<T>[];
|
|
27
|
+
xAxis?: SimpleAxisOptions;
|
|
28
|
+
yAxis?: SimpleAxisOptions;
|
|
29
|
+
bands?: BandSpec[];
|
|
30
|
+
lines?: PlotLineSpec[];
|
|
31
|
+
grid?: boolean;
|
|
32
|
+
tooltip?: boolean | TooltipSpec;
|
|
33
|
+
legend?: boolean | LegendSpec;
|
|
34
|
+
plotOptions?: PlotOptions<T>;
|
|
35
|
+
padding?: Padding;
|
|
36
|
+
label?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface Props extends BaseProps {
|
|
41
|
+
responsive?: ResponsiveRule<BaseProps>[];
|
|
42
|
+
class?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let {
|
|
46
|
+
series,
|
|
47
|
+
xAxis,
|
|
48
|
+
yAxis,
|
|
49
|
+
bands,
|
|
50
|
+
lines,
|
|
51
|
+
grid = true,
|
|
52
|
+
tooltip = true,
|
|
53
|
+
legend,
|
|
54
|
+
plotOptions,
|
|
55
|
+
padding,
|
|
56
|
+
label = 'Box plot',
|
|
57
|
+
description,
|
|
58
|
+
responsive,
|
|
59
|
+
class: klass = ''
|
|
60
|
+
}: Props = $props();
|
|
61
|
+
|
|
62
|
+
let width = $state(0);
|
|
63
|
+
|
|
64
|
+
const eff = $derived(
|
|
65
|
+
applyResponsive(
|
|
66
|
+
{ series, xAxis, yAxis, bands, lines, grid, tooltip, legend, plotOptions, padding, label, description },
|
|
67
|
+
responsive,
|
|
68
|
+
width
|
|
69
|
+
)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const resolved = $derived(eff.series.map((s) => resolveSeries(eff.plotOptions, s)));
|
|
73
|
+
const xa = $derived(splitAxisOptions(eff.xAxis));
|
|
74
|
+
const ya = $derived(splitAxisOptions(eff.yAxis));
|
|
75
|
+
|
|
76
|
+
const legendOn = $derived(eff.legend === undefined ? eff.series.length > 1 : eff.legend !== false);
|
|
77
|
+
const legendPos = $derived(
|
|
78
|
+
typeof eff.legend === 'object' && eff.legend ? (eff.legend.position ?? 'bottom') : 'bottom'
|
|
79
|
+
);
|
|
80
|
+
const tooltipOn = $derived(eff.tooltip !== false);
|
|
81
|
+
const tip = $derived(typeof eff.tooltip === 'object' && eff.tooltip ? eff.tooltip : {});
|
|
82
|
+
const pad = $derived({
|
|
83
|
+
...(legendOn ? (legendPos === 'top' ? { top: 48 } : { bottom: 56 }) : {}),
|
|
84
|
+
...eff.padding
|
|
85
|
+
});
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<div class="fc-simple fc-box-chart {klass}" bind:clientWidth={width}>
|
|
89
|
+
<Chart x={xa.scale} y={ya.scale} padding={pad} label={eff.label} description={eff.description}>
|
|
90
|
+
<Svg>
|
|
91
|
+
{#if eff.grid}<Grid y />{/if}
|
|
92
|
+
{#each eff.bands ?? [] as band, i (i)}
|
|
93
|
+
<PlotBand axis={band.axis} from={band.from} to={band.to} color={band.color} label={band.label} />
|
|
94
|
+
{/each}
|
|
95
|
+
{#each resolved as s, i (i)}
|
|
96
|
+
<Box
|
|
97
|
+
data={s.data}
|
|
98
|
+
x={s.x}
|
|
99
|
+
low={s.low}
|
|
100
|
+
q1={s.q1}
|
|
101
|
+
median={s.median}
|
|
102
|
+
q3={s.q3}
|
|
103
|
+
high={s.high}
|
|
104
|
+
outliers={s.outliers}
|
|
105
|
+
samples={s.samples}
|
|
106
|
+
whisker={s.whisker}
|
|
107
|
+
whiskerK={s.whiskerK}
|
|
108
|
+
color={s.color}
|
|
109
|
+
colorFor={s.colorFor}
|
|
110
|
+
name={s.name}
|
|
111
|
+
description={s.description}
|
|
112
|
+
boxPadding={s.boxPadding}
|
|
113
|
+
index={i}
|
|
114
|
+
/>
|
|
115
|
+
{/each}
|
|
116
|
+
{#each eff.lines ?? [] as pl, i (i)}
|
|
117
|
+
<PlotLine axis={pl.axis} value={pl.value} color={pl.color} dash={pl.dash} label={pl.label} />
|
|
118
|
+
{/each}
|
|
119
|
+
{#if xa.visible}
|
|
120
|
+
<Axis placement="bottom" title={xa.display.title} ticks={xa.display.ticks} format={xa.display.format} rotate={xa.display.rotate} />
|
|
121
|
+
{/if}
|
|
122
|
+
{#if ya.visible}
|
|
123
|
+
<Axis placement="left" title={ya.display.title} ticks={ya.display.ticks} format={ya.display.format} rotate={ya.display.rotate} />
|
|
124
|
+
{/if}
|
|
125
|
+
</Svg>
|
|
126
|
+
{#if tooltipOn}
|
|
127
|
+
<Tooltip mode={tip.mode ?? 'band'} shared={tip.shared ?? true} formatX={tip.formatX} formatY={tip.formatY} />
|
|
128
|
+
{/if}
|
|
129
|
+
{#if legendOn}<Legend position={legendPos} />{/if}
|
|
130
|
+
</Chart>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<style>
|
|
134
|
+
.fc-simple {
|
|
135
|
+
width: 100%;
|
|
136
|
+
height: 100%;
|
|
137
|
+
}
|
|
138
|
+
</style>
|