@rokkit/chart 1.1.18 → 1.2.0
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/dist/AnimatedPlot.svelte.d.ts +35 -0
- package/dist/Chart.svelte.d.ts +21 -0
- package/dist/ChartExporter.svelte.d.ts +22 -0
- package/dist/ChartLegend.svelte.d.ts +30 -0
- package/dist/ChartProvider.svelte.d.ts +10 -0
- package/dist/FacetPlot/Panel.svelte.d.ts +22 -0
- package/dist/FacetPlot.svelte.d.ts +32 -0
- package/dist/Plot/Arc.svelte.d.ts +18 -0
- package/dist/Plot/Area.svelte.d.ts +14 -0
- package/dist/Plot/Axis.svelte.d.ts +13 -0
- package/dist/Plot/Bar.svelte.d.ts +11 -0
- package/dist/Plot/Grid.svelte.d.ts +3 -0
- package/dist/Plot/Legend.svelte.d.ts +6 -0
- package/dist/Plot/Line.svelte.d.ts +13 -0
- package/dist/Plot/Point.svelte.d.ts +13 -0
- package/dist/Plot/Root.svelte.d.ts +21 -0
- package/dist/Plot/Timeline.svelte.d.ts +13 -0
- package/dist/Plot/Tooltip.svelte.d.ts +7 -0
- package/dist/Plot.svelte.d.ts +34 -0
- package/dist/PlotState.svelte.d.ts +0 -3
- package/dist/Sparkline.svelte.d.ts +16 -0
- package/dist/Symbol.svelte.d.ts +12 -0
- package/dist/Texture.svelte.d.ts +12 -0
- package/dist/charts/AreaChart.svelte.d.ts +25 -0
- package/dist/charts/BarChart.svelte.d.ts +26 -0
- package/dist/charts/BoxPlot.svelte.d.ts +18 -0
- package/dist/charts/BubbleChart.svelte.d.ts +23 -0
- package/dist/charts/LineChart.svelte.d.ts +26 -0
- package/dist/charts/PieChart.svelte.d.ts +19 -0
- package/dist/charts/ScatterPlot.svelte.d.ts +29 -0
- package/dist/charts/ViolinPlot.svelte.d.ts +18 -0
- package/dist/crossfilter/CrossFilter.svelte.d.ts +12 -0
- package/dist/crossfilter/FilterBar.svelte.d.ts +12 -0
- package/dist/crossfilter/FilterHistogram.svelte.d.ts +19 -0
- package/dist/crossfilter/FilterSlider.svelte.d.ts +15 -0
- package/dist/elements/Bar.svelte.d.ts +17 -0
- package/dist/elements/ColorRamp.svelte.d.ts +17 -0
- package/dist/elements/ContinuousLegend.svelte.d.ts +18 -0
- package/dist/elements/DefinePatterns.svelte.d.ts +21 -0
- package/dist/elements/DiscreteLegend.svelte.d.ts +17 -0
- package/dist/elements/Label.svelte.d.ts +11 -0
- package/dist/elements/SymbolGrid.svelte.d.ts +8 -0
- package/dist/examples/BarChartExample.svelte.d.ts +18 -0
- package/dist/geoms/Arc.svelte.d.ts +20 -0
- package/dist/geoms/Area.svelte.d.ts +16 -0
- package/dist/geoms/Bar.svelte.d.ts +23 -0
- package/dist/geoms/Box.svelte.d.ts +12 -0
- package/dist/geoms/Candlestick.svelte.d.ts +20 -0
- package/dist/geoms/Heatmap.svelte.d.ts +13 -0
- package/dist/geoms/Hexbin.svelte.d.ts +13 -0
- package/dist/geoms/LabelPill.svelte.d.ts +9 -0
- package/dist/geoms/Line.svelte.d.ts +24 -0
- package/dist/geoms/Point.svelte.d.ts +30 -0
- package/dist/geoms/Ribbon.svelte.d.ts +16 -0
- package/dist/geoms/Violin.svelte.d.ts +12 -0
- package/dist/geoms/Waterfall.svelte.d.ts +18 -0
- package/dist/geoms/lib/areas.d.ts +5 -3
- package/dist/lib/brewing/brewer.svelte.d.ts +24 -15
- package/dist/lib/brewing/marks/arcs.d.ts +16 -6
- package/dist/lib/brewing/marks/areas.d.ts +2 -2
- package/dist/lib/brewing/marks/boxes.d.ts +3 -3
- package/dist/lib/brewing/marks/lines.d.ts +6 -6
- package/dist/lib/brewing/marks/points.d.ts +13 -12
- package/dist/lib/brewing/marks/violins.d.ts +3 -3
- package/dist/lib/brewing/scales.d.ts +3 -3
- package/dist/lib/chart.d.ts +2 -2
- package/dist/lib/keyboard-nav.d.ts +1 -1
- package/dist/lib/plot/facet.d.ts +2 -2
- package/dist/lib/plot/frames.d.ts +9 -9
- package/dist/lib/plot/scales.d.ts +3 -3
- package/dist/lib/plot/types.d.ts +7 -4
- package/dist/lib/scales.svelte.d.ts +2 -2
- package/dist/lib/utils.d.ts +7 -1
- package/dist/lib/xscale.d.ts +1 -1
- package/dist/patterns/DefinePatterns.svelte.d.ts +7 -0
- package/dist/patterns/PatternDef.svelte.d.ts +11 -0
- package/dist/spec/chart-spec.d.ts +22 -0
- package/dist/symbols/RoundedSquare.svelte.d.ts +11 -0
- package/dist/symbols/Shape.svelte.d.ts +18 -0
- package/dist/symbols/constants/index.d.ts +1 -1
- package/dist/symbols/index.d.ts +2 -2
- package/dist/symbols/outline.svelte.d.ts +18 -0
- package/dist/symbols/solid.svelte.d.ts +18 -0
- package/package.json +22 -3
- package/src/AnimatedPlot.svelte +49 -43
- package/src/Chart.svelte +34 -22
- package/src/ChartExporter.svelte +19 -16
- package/src/ChartLegend.svelte +24 -20
- package/src/ChartProvider.svelte +10 -2
- package/src/FacetPlot/Panel.svelte +23 -3
- package/src/FacetPlot.svelte +29 -26
- package/src/Plot/Arc.svelte +3 -2
- package/src/Plot/Area.svelte +30 -8
- package/src/Plot/Axis.svelte +26 -45
- package/src/Plot/Bar.svelte +20 -5
- package/src/Plot/Grid.svelte +5 -4
- package/src/Plot/Legend.svelte +8 -4
- package/src/Plot/Line.svelte +24 -7
- package/src/Plot/Point.svelte +24 -6
- package/src/Plot/Root.svelte +17 -2
- package/src/Plot/Timeline.svelte +13 -14
- package/src/Plot/Tooltip.svelte +12 -6
- package/src/Plot.svelte +41 -32
- package/src/PlotState.svelte.js +6 -2
- package/src/Sparkline.svelte +22 -8
- package/src/Symbol.svelte +15 -5
- package/src/Texture.svelte +12 -2
- package/src/charts/AreaChart.svelte +26 -3
- package/src/charts/BarChart.svelte +27 -3
- package/src/charts/BoxPlot.svelte +19 -3
- package/src/charts/BubbleChart.svelte +24 -3
- package/src/charts/LineChart.svelte +27 -3
- package/src/charts/PieChart.svelte +20 -3
- package/src/charts/ScatterPlot.svelte +27 -3
- package/src/charts/ViolinPlot.svelte +19 -3
- package/src/crossfilter/CrossFilter.svelte +13 -10
- package/src/crossfilter/FilterBar.svelte +14 -3
- package/src/crossfilter/FilterHistogram.svelte +49 -24
- package/src/crossfilter/FilterSlider.svelte +16 -5
- package/src/elements/Bar.svelte +16 -2
- package/src/elements/ColorRamp.svelte +28 -4
- package/src/elements/ContinuousLegend.svelte +20 -3
- package/src/elements/DefinePatterns.svelte +23 -7
- package/src/elements/DiscreteLegend.svelte +18 -2
- package/src/elements/Label.svelte +11 -2
- package/src/elements/SymbolGrid.svelte +13 -4
- package/src/examples/BarChartExample.svelte +12 -15
- package/src/geoms/Arc.svelte +18 -5
- package/src/geoms/Area.svelte +38 -20
- package/src/geoms/Bar.svelte +40 -23
- package/src/geoms/Box.svelte +13 -4
- package/src/geoms/Candlestick.svelte +27 -7
- package/src/geoms/Heatmap.svelte +20 -9
- package/src/geoms/Hexbin.svelte +35 -13
- package/src/geoms/LabelPill.svelte +9 -3
- package/src/geoms/Line.svelte +27 -10
- package/src/geoms/Point.svelte +33 -13
- package/src/geoms/Ribbon.svelte +26 -8
- package/src/geoms/Violin.svelte +13 -4
- package/src/geoms/Waterfall.svelte +32 -12
- package/src/geoms/lib/areas.js +2 -2
- package/src/lib/brewing/marks/arcs.js +3 -2
- package/src/lib/brewing/marks/boxes.js +1 -1
- package/src/lib/brewing/marks/lines.js +2 -2
- package/src/lib/brewing/marks/points.js +3 -2
- package/src/lib/brewing/marks/violins.js +1 -1
- package/src/lib/plot/facet.js +1 -1
- package/src/lib/plot/frames.js +4 -4
- package/src/lib/plot/types.js +6 -3
- package/src/lib/utils.js +7 -1
- package/src/patterns/DefinePatterns.svelte +9 -4
- package/src/patterns/PatternDef.svelte +11 -3
- package/src/symbols/RoundedSquare.svelte +15 -4
- package/src/symbols/Shape.svelte +21 -3
- package/src/symbols/outline.svelte +2 -0
- package/src/symbols/solid.svelte +2 -0
package/src/ChartExporter.svelte
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte'
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
5
|
* ChartExporter — wraps a chart and provides export actions for SVG and PNG.
|
|
4
6
|
*
|
|
@@ -9,26 +11,30 @@
|
|
|
9
11
|
* <button onclick={() => exporter.exportSVG()}>SVG</button>
|
|
10
12
|
* <button onclick={() => exporter.exportPNG()}>PNG</button>
|
|
11
13
|
*/
|
|
14
|
+
type Props = {
|
|
15
|
+
children?: Snippet
|
|
16
|
+
filename?: string
|
|
17
|
+
scale?: number
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
let {
|
|
13
21
|
children,
|
|
14
22
|
filename = 'chart',
|
|
15
23
|
scale = 2
|
|
16
|
-
} = $props()
|
|
24
|
+
}: Props = $props()
|
|
17
25
|
|
|
18
|
-
let containerEl = $state(null)
|
|
26
|
+
let containerEl = $state<HTMLDivElement | null>(null)
|
|
19
27
|
|
|
20
|
-
function getSvgEl() {
|
|
21
|
-
return containerEl?.querySelector('svg')
|
|
28
|
+
function getSvgEl(): SVGSVGElement | null {
|
|
29
|
+
return containerEl?.querySelector('svg') ?? null
|
|
22
30
|
}
|
|
23
31
|
|
|
24
32
|
/**
|
|
25
33
|
* Inline all computed CSS custom property values into the SVG for portability.
|
|
26
|
-
* @param {SVGSVGElement} svg
|
|
27
|
-
* @returns {SVGSVGElement}
|
|
28
34
|
*/
|
|
29
35
|
// eslint-disable-next-line complexity
|
|
30
|
-
function inlineStyles(svg) {
|
|
31
|
-
const clone =
|
|
36
|
+
function inlineStyles(svg: SVGSVGElement): SVGSVGElement {
|
|
37
|
+
const clone = svg.cloneNode(true) as SVGSVGElement
|
|
32
38
|
const computed = getComputedStyle(svg)
|
|
33
39
|
|
|
34
40
|
// Copy relevant CSS custom properties to inline styles on the root
|
|
@@ -70,9 +76,9 @@
|
|
|
70
76
|
|
|
71
77
|
/**
|
|
72
78
|
* Export the chart as a PNG file download.
|
|
73
|
-
* @param
|
|
79
|
+
* @param scaleFactor Override scale factor for this export
|
|
74
80
|
*/
|
|
75
|
-
export function exportPNG(scaleFactor) {
|
|
81
|
+
export function exportPNG(scaleFactor?: number) {
|
|
76
82
|
const svg = getSvgEl()
|
|
77
83
|
if (!svg) return
|
|
78
84
|
|
|
@@ -89,6 +95,7 @@
|
|
|
89
95
|
canvas.width = svg.clientWidth * factor
|
|
90
96
|
canvas.height = svg.clientHeight * factor
|
|
91
97
|
const ctx = canvas.getContext('2d')
|
|
98
|
+
if (!ctx) return
|
|
92
99
|
ctx.scale(factor, factor)
|
|
93
100
|
ctx.drawImage(img, 0, 0)
|
|
94
101
|
URL.revokeObjectURL(url)
|
|
@@ -100,11 +107,7 @@
|
|
|
100
107
|
img.src = url
|
|
101
108
|
}
|
|
102
109
|
|
|
103
|
-
|
|
104
|
-
* @param {Blob} blob
|
|
105
|
-
* @param {string} name
|
|
106
|
-
*/
|
|
107
|
-
function download(blob, name) {
|
|
110
|
+
function download(blob: Blob, name: string) {
|
|
108
111
|
const a = document.createElement('a')
|
|
109
112
|
a.href = URL.createObjectURL(blob)
|
|
110
113
|
a.download = name
|
package/src/ChartLegend.svelte
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { buildSymbolPath } from './lib/brewing/marks/points.js'
|
|
3
3
|
|
|
4
|
+
type LegendItem = {
|
|
5
|
+
key: string
|
|
6
|
+
label: string
|
|
7
|
+
fill?: string
|
|
8
|
+
stroke?: string
|
|
9
|
+
patternId?: string
|
|
10
|
+
shape?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type LegendGroup = {
|
|
14
|
+
type?: 'color' | 'pattern' | 'symbol'
|
|
15
|
+
label?: string
|
|
16
|
+
items: LegendItem[]
|
|
17
|
+
}
|
|
18
|
+
|
|
4
19
|
/**
|
|
5
20
|
* Standalone chart legend — HTML-based, usable outside of Plot context.
|
|
6
21
|
* Accepts `groups` from a chart's brewer or from multiple charts for shared legends.
|
|
7
|
-
*
|
|
8
|
-
* @type {{
|
|
9
|
-
* groups: Array<{
|
|
10
|
-
* type?: 'color' | 'pattern' | 'symbol',
|
|
11
|
-
* label?: string,
|
|
12
|
-
* items: Array<{
|
|
13
|
-
* key: string,
|
|
14
|
-
* label: string,
|
|
15
|
-
* fill?: string,
|
|
16
|
-
* stroke?: string,
|
|
17
|
-
* patternId?: string,
|
|
18
|
-
* shape?: string,
|
|
19
|
-
* }>
|
|
20
|
-
* }>,
|
|
21
|
-
* orientation?: 'horizontal' | 'vertical' | 'wrap',
|
|
22
|
-
* gradient?: { style: string, min: string, max: string } | null,
|
|
23
|
-
* swatchStyle?: 'fill' | 'line' | 'point',
|
|
24
|
-
* }}
|
|
25
22
|
*/
|
|
23
|
+
type Props = {
|
|
24
|
+
groups?: LegendGroup[]
|
|
25
|
+
orientation?: 'horizontal' | 'vertical' | 'wrap'
|
|
26
|
+
gradient?: { style: string; min: string; max: string } | null
|
|
27
|
+
swatchStyle?: 'fill' | 'line' | 'point'
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
let {
|
|
27
31
|
groups = [],
|
|
28
32
|
orientation = 'horizontal',
|
|
29
33
|
gradient = null,
|
|
30
34
|
swatchStyle = 'fill'
|
|
31
|
-
} = $props()
|
|
35
|
+
}: Props = $props()
|
|
32
36
|
</script>
|
|
33
37
|
|
|
34
38
|
<div
|
package/src/ChartProvider.svelte
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { setContext } from 'svelte'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
3
4
|
import { createChartPreset } from './lib/preset.js'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
type Preset = ReturnType<typeof createChartPreset>
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
preset?: Preset
|
|
10
|
+
children?: Snippet
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { preset = createChartPreset(), children }: Props = $props()
|
|
6
14
|
|
|
7
15
|
setContext('chart-preset', { get current() { return preset } })
|
|
8
16
|
</script>
|
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte'
|
|
2
3
|
import PlotChart from '../Plot.svelte'
|
|
4
|
+
import type { GeomSpec, PlotHelpers } from '../lib/plot/types.js'
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
data?: Record<string, unknown>[]
|
|
8
|
+
x?: string
|
|
9
|
+
y?: string
|
|
10
|
+
color?: string
|
|
11
|
+
geoms?: GeomSpec[]
|
|
12
|
+
helpers?: PlotHelpers
|
|
13
|
+
width?: number
|
|
14
|
+
height?: number
|
|
15
|
+
mode?: 'light' | 'dark'
|
|
16
|
+
grid?: boolean
|
|
17
|
+
legend?: boolean
|
|
18
|
+
xDomain?: unknown[]
|
|
19
|
+
yDomain?: [number, number]
|
|
20
|
+
colorDomain?: unknown[]
|
|
21
|
+
children?: Snippet
|
|
22
|
+
}
|
|
3
23
|
|
|
4
24
|
let {
|
|
5
|
-
data,
|
|
25
|
+
data = [],
|
|
6
26
|
x,
|
|
7
27
|
y,
|
|
8
28
|
color,
|
|
@@ -17,7 +37,7 @@
|
|
|
17
37
|
yDomain,
|
|
18
38
|
colorDomain,
|
|
19
39
|
children
|
|
20
|
-
} = $props()
|
|
40
|
+
}: Props = $props()
|
|
21
41
|
|
|
22
42
|
// Build spec with domain overrides so PlotState uses them
|
|
23
43
|
const spec = $derived({
|
package/src/FacetPlot.svelte
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte'
|
|
2
3
|
import { splitByField, getFacetDomains } from './lib/plot/facet.js'
|
|
3
4
|
import { distinct } from './lib/brewing/colors.js'
|
|
5
|
+
import type { GeomSpec, PlotHelpers } from './lib/plot/types.js'
|
|
4
6
|
import PlotPanel from './FacetPlot/Panel.svelte'
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
type Facet = { by: string; cols?: number; scales?: 'fixed' | 'free' | 'free_x' | 'free_y' }
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
data?: Record<string, unknown>[]
|
|
12
|
+
facet: Facet
|
|
13
|
+
x?: string
|
|
14
|
+
y?: string
|
|
15
|
+
color?: string
|
|
16
|
+
fill?: string
|
|
17
|
+
pattern?: string
|
|
18
|
+
symbol?: string
|
|
19
|
+
geom?: string
|
|
20
|
+
stat?: string
|
|
21
|
+
geoms?: GeomSpec[]
|
|
22
|
+
helpers?: PlotHelpers
|
|
23
|
+
panelWidth?: number
|
|
24
|
+
panelHeight?: number
|
|
25
|
+
width?: number
|
|
26
|
+
height?: number
|
|
27
|
+
mode?: 'light' | 'dark'
|
|
28
|
+
grid?: boolean
|
|
29
|
+
legend?: boolean
|
|
30
|
+
children?: Snippet
|
|
31
|
+
}
|
|
32
|
+
|
|
30
33
|
let {
|
|
31
34
|
data = [],
|
|
32
35
|
facet,
|
|
@@ -48,7 +51,7 @@
|
|
|
48
51
|
grid = true,
|
|
49
52
|
legend = false,
|
|
50
53
|
children
|
|
51
|
-
} = $props()
|
|
54
|
+
}: Props = $props()
|
|
52
55
|
|
|
53
56
|
// `fill` is accepted as an alias for `color` (bar/area semantics vs line/point)
|
|
54
57
|
const colorChannel = $derived(fill ?? color)
|
package/src/Plot/Arc.svelte
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { ChartBrewer } from '../lib/brewing/brewer.svelte.js'
|
|
3
4
|
|
|
4
|
-
const brewer = getContext('chart-brewer')
|
|
5
|
+
const brewer = getContext<ChartBrewer>('chart-brewer')
|
|
5
6
|
</script>
|
|
6
7
|
|
|
7
8
|
{#if brewer && brewer.arcs && brewer.arcs.length > 0}
|
package/src/Plot/Area.svelte
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
-
import { area as d3Area } from 'd3-shape'
|
|
3
|
+
import { area as d3Area, type CurveFactory } from 'd3-shape'
|
|
4
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
5
|
+
|
|
6
|
+
type Datum = Record<string, unknown> | number
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
data?: Datum[]
|
|
10
|
+
x?: string
|
|
11
|
+
y?: string
|
|
12
|
+
y0?: string
|
|
13
|
+
fill?: string
|
|
14
|
+
opacity?: number
|
|
15
|
+
curve?: CurveFactory
|
|
16
|
+
}
|
|
4
17
|
|
|
5
18
|
let {
|
|
6
19
|
data = [],
|
|
@@ -10,17 +23,26 @@
|
|
|
10
23
|
fill = 'steelblue',
|
|
11
24
|
opacity = 0.7,
|
|
12
25
|
curve = undefined
|
|
13
|
-
} = $props()
|
|
26
|
+
}: Props = $props()
|
|
27
|
+
|
|
28
|
+
const state = getContext<PlotState>('plot-state')
|
|
14
29
|
|
|
15
|
-
const
|
|
30
|
+
const accessor = (d: Datum, field: string | undefined): unknown =>
|
|
31
|
+
field && typeof d === 'object' ? d[field] : d
|
|
16
32
|
|
|
17
33
|
const path = $derived.by(() => {
|
|
18
34
|
if (!state?.xScale || !state?.yScale || !data?.length) return null
|
|
35
|
+
const xScale = state.xScale
|
|
36
|
+
const yScale = state.yScale
|
|
19
37
|
const innerHeight = state.innerHeight
|
|
20
|
-
const areaGen = d3Area()
|
|
21
|
-
.x((d) =>
|
|
22
|
-
.y1((d) =>
|
|
23
|
-
.y0((d) =>
|
|
38
|
+
const areaGen = d3Area<Datum>()
|
|
39
|
+
.x((d) => xScale(accessor(d, x)) ?? 0)
|
|
40
|
+
.y1((d) => yScale(accessor(d, y)) ?? 0)
|
|
41
|
+
.y0((d) =>
|
|
42
|
+
y0 !== undefined
|
|
43
|
+
? (yScale((typeof d === 'object' ? d[y0] : undefined) ?? y0) ?? innerHeight)
|
|
44
|
+
: innerHeight
|
|
45
|
+
)
|
|
24
46
|
.defined((d) => d != null)
|
|
25
47
|
if (curve) areaGen.curve(curve)
|
|
26
48
|
return areaGen(data)
|
package/src/Plot/Axis.svelte
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
type?: 'x' | 'y'
|
|
7
|
+
label?: string
|
|
8
|
+
format?: (v: unknown) => string
|
|
9
|
+
ticks?: number
|
|
10
|
+
minorTicks?: boolean
|
|
11
|
+
showLine?: boolean
|
|
12
|
+
showTicks?: boolean
|
|
13
|
+
showLabels?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Tick = { value: unknown; pos: number; minor: boolean }
|
|
3
17
|
|
|
4
|
-
/**
|
|
5
|
-
* @type {{
|
|
6
|
-
* type?: 'x' | 'y',
|
|
7
|
-
* label?: string,
|
|
8
|
-
* format?: (v: unknown) => string,
|
|
9
|
-
* ticks?: number,
|
|
10
|
-
* minorTicks?: boolean,
|
|
11
|
-
* showLine?: boolean,
|
|
12
|
-
* showTicks?: boolean,
|
|
13
|
-
* showLabels?: boolean,
|
|
14
|
-
* }}
|
|
15
|
-
*/
|
|
16
18
|
let {
|
|
17
19
|
type = 'x',
|
|
18
20
|
label = '',
|
|
@@ -22,25 +24,26 @@
|
|
|
22
24
|
showLine = true,
|
|
23
25
|
showTicks = true,
|
|
24
26
|
showLabels = true
|
|
25
|
-
} = $props()
|
|
27
|
+
}: Props = $props()
|
|
26
28
|
|
|
27
|
-
const state = getContext('plot-state')
|
|
29
|
+
const state = getContext<PlotState>('plot-state')
|
|
28
30
|
|
|
29
31
|
const MINOR_DIVISIONS = 4
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
const s = state.xScale
|
|
33
|
+
function buildTicks(s: PlotState['xScale']): Tick[] {
|
|
33
34
|
if (!s) return []
|
|
34
35
|
if (typeof s.bandwidth === 'function') {
|
|
35
|
-
return s.domain().map((val) => ({
|
|
36
|
+
return s.domain().map((val: unknown) => ({
|
|
36
37
|
value: val,
|
|
37
38
|
pos: (s(val) ?? 0) + s.bandwidth() / 2,
|
|
38
39
|
minor: false
|
|
39
40
|
}))
|
|
40
41
|
}
|
|
41
|
-
const major
|
|
42
|
+
const major: Tick[] = s
|
|
43
|
+
.ticks(tickCount)
|
|
44
|
+
.map((val: number) => ({ value: val, pos: s(val), minor: false }))
|
|
42
45
|
if (!minorTicks || major.length < 2) return major
|
|
43
|
-
const result = []
|
|
46
|
+
const result: Tick[] = []
|
|
44
47
|
for (let i = 0; i < major.length; i++) {
|
|
45
48
|
result.push(major[i])
|
|
46
49
|
if (i < major.length - 1) {
|
|
@@ -51,32 +54,10 @@
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
return result
|
|
54
|
-
}
|
|
57
|
+
}
|
|
55
58
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
if (!s) return []
|
|
59
|
-
if (typeof s.bandwidth === 'function') {
|
|
60
|
-
return s.domain().map((val) => ({
|
|
61
|
-
value: val,
|
|
62
|
-
pos: (s(val) ?? 0) + s.bandwidth() / 2,
|
|
63
|
-
minor: false
|
|
64
|
-
}))
|
|
65
|
-
}
|
|
66
|
-
const major = s.ticks(tickCount).map((val) => ({ value: val, pos: s(val), minor: false }))
|
|
67
|
-
if (!minorTicks || major.length < 2) return major
|
|
68
|
-
const result = []
|
|
69
|
-
for (let i = 0; i < major.length; i++) {
|
|
70
|
-
result.push(major[i])
|
|
71
|
-
if (i < major.length - 1) {
|
|
72
|
-
const step = (major[i + 1].pos - major[i].pos) / MINOR_DIVISIONS
|
|
73
|
-
for (let j = 1; j < MINOR_DIVISIONS; j++) {
|
|
74
|
-
result.push({ value: null, pos: major[i].pos + step * j, minor: true })
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return result
|
|
79
|
-
})
|
|
59
|
+
const xTicks = $derived(buildTicks(state.xScale))
|
|
60
|
+
const yTicks = $derived(buildTicks(state.yScale))
|
|
80
61
|
|
|
81
62
|
const xTransform = $derived(`translate(0, ${state.xAxisY ?? state.innerHeight})`)
|
|
82
63
|
const yTransform = $derived(`translate(${state.yAxisX ?? 0}, 0)`)
|
package/src/Plot/Bar.svelte
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
type Datum = Record<string, unknown> | number
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
type Props = {
|
|
8
|
+
data?: Datum[]
|
|
9
|
+
x?: string
|
|
10
|
+
y?: string
|
|
11
|
+
fill?: string
|
|
12
|
+
opacity?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { data = undefined, x = undefined, y = undefined, fill = 'steelblue', opacity = 1 }: Props =
|
|
16
|
+
$props()
|
|
17
|
+
|
|
18
|
+
const state = getContext<PlotState>('plot-state')
|
|
19
|
+
|
|
20
|
+
const accessor = (d: Datum, field: string | undefined): unknown =>
|
|
21
|
+
field && typeof d === 'object' ? d[field] : d
|
|
7
22
|
|
|
8
23
|
const bars = $derived.by(() => {
|
|
9
24
|
if (!state?.xScale || !state?.yScale) return []
|
|
@@ -24,8 +39,8 @@
|
|
|
24
39
|
: innerHeight
|
|
25
40
|
|
|
26
41
|
return src.map((d) => {
|
|
27
|
-
const xVal =
|
|
28
|
-
const yVal =
|
|
42
|
+
const xVal = accessor(d, x)
|
|
43
|
+
const yVal = accessor(d, y)
|
|
29
44
|
const xPos = (xScale(xVal) ?? 0) + padding
|
|
30
45
|
const yPos = yScale(yVal) ?? baseline
|
|
31
46
|
return {
|
package/src/Plot/Grid.svelte
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
3
4
|
|
|
4
|
-
const state = getContext('plot-state')
|
|
5
|
+
const state = getContext<PlotState>('plot-state')
|
|
5
6
|
|
|
6
7
|
const xGridLines = $derived.by(() => {
|
|
7
8
|
const s = state.xScale
|
|
8
9
|
if (!s || typeof s.bandwidth !== 'function') return []
|
|
9
|
-
return s.domain().map((val) => ({ pos: (s(val) ?? 0) + s.bandwidth() / 2 }))
|
|
10
|
+
return s.domain().map((val: unknown) => ({ pos: (s(val) ?? 0) + s.bandwidth() / 2 }))
|
|
10
11
|
})
|
|
11
12
|
|
|
12
13
|
const yGridLines = $derived.by(() => {
|
|
13
14
|
const s = state.yScale
|
|
14
15
|
if (!s || typeof s.ticks !== 'function') return []
|
|
15
|
-
return s.ticks(6).map((val) => ({ pos: s(val) }))
|
|
16
|
+
return s.ticks(6).map((val: number) => ({ pos: s(val) }))
|
|
16
17
|
})
|
|
17
18
|
</script>
|
|
18
19
|
|
package/src/Plot/Legend.svelte
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
3
4
|
import { toPatternId } from '../lib/brewing/patterns.js'
|
|
4
5
|
import { buildSymbolPath } from '../lib/brewing/marks/points.js'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
type Props = {
|
|
8
|
+
labels?: Record<string, string>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { labels = {} }: Props = $props()
|
|
8
12
|
|
|
9
|
-
const state = getContext('plot-state')
|
|
13
|
+
const state = getContext<PlotState>('plot-state')
|
|
10
14
|
|
|
11
15
|
const isCategorical = $derived(state.colorScaleType === 'categorical')
|
|
12
16
|
const isLineGeom = $derived(state.geomTypes?.has('line') ?? false)
|
package/src/Plot/Line.svelte
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
-
import { line as d3Line } from 'd3-shape'
|
|
3
|
+
import { line as d3Line, type CurveFactory } from 'd3-shape'
|
|
4
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
5
|
+
|
|
6
|
+
type Datum = Record<string, unknown> | number
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
data?: Datum[]
|
|
10
|
+
x?: string
|
|
11
|
+
y?: string
|
|
12
|
+
stroke?: string
|
|
13
|
+
strokeWidth?: number
|
|
14
|
+
curve?: CurveFactory
|
|
15
|
+
}
|
|
4
16
|
|
|
5
17
|
let {
|
|
6
18
|
data = [],
|
|
@@ -9,15 +21,20 @@
|
|
|
9
21
|
stroke = 'steelblue',
|
|
10
22
|
strokeWidth = 2,
|
|
11
23
|
curve = undefined
|
|
12
|
-
} = $props()
|
|
24
|
+
}: Props = $props()
|
|
25
|
+
|
|
26
|
+
const state = getContext<PlotState>('plot-state')
|
|
13
27
|
|
|
14
|
-
const
|
|
28
|
+
const accessor = (d: Datum, field: string | undefined): unknown =>
|
|
29
|
+
field && typeof d === 'object' ? d[field] : d
|
|
15
30
|
|
|
16
31
|
const path = $derived.by(() => {
|
|
17
32
|
if (!state?.xScale || !state?.yScale || !data?.length) return null
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
const xScale = state.xScale
|
|
34
|
+
const yScale = state.yScale
|
|
35
|
+
const lineGen = d3Line<Datum>()
|
|
36
|
+
.x((d) => xScale(accessor(d, x)) ?? 0)
|
|
37
|
+
.y((d) => yScale(accessor(d, y)) ?? 0)
|
|
21
38
|
.defined((d) => d != null)
|
|
22
39
|
if (curve) lineGen.curve(curve)
|
|
23
40
|
return lineGen(data)
|
package/src/Plot/Point.svelte
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { getContext } from 'svelte'
|
|
3
|
+
import type { PlotState } from '../PlotState.svelte.js'
|
|
4
|
+
|
|
5
|
+
type Datum = Record<string, unknown> | number
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
data?: Datum[]
|
|
9
|
+
x?: string
|
|
10
|
+
y?: string
|
|
11
|
+
r?: number
|
|
12
|
+
fill?: string
|
|
13
|
+
stroke?: string
|
|
14
|
+
strokeWidth?: number
|
|
15
|
+
}
|
|
3
16
|
|
|
4
17
|
let {
|
|
5
18
|
data = [],
|
|
@@ -9,17 +22,22 @@
|
|
|
9
22
|
fill = 'steelblue',
|
|
10
23
|
stroke = 'white',
|
|
11
24
|
strokeWidth = 1
|
|
12
|
-
} = $props()
|
|
25
|
+
}: Props = $props()
|
|
26
|
+
|
|
27
|
+
const state = getContext<PlotState>('plot-state')
|
|
13
28
|
|
|
14
|
-
const
|
|
29
|
+
const accessor = (d: Datum, field: string | undefined): unknown =>
|
|
30
|
+
field && typeof d === 'object' ? d[field] : d
|
|
15
31
|
|
|
16
32
|
const points = $derived.by(() => {
|
|
17
33
|
if (!state?.xScale || !state?.yScale || !data?.length) return []
|
|
34
|
+
const xScale = state.xScale
|
|
35
|
+
const yScale = state.yScale
|
|
18
36
|
return data
|
|
19
37
|
.map((d) => ({
|
|
20
|
-
cx:
|
|
21
|
-
cy:
|
|
22
|
-
label: `(${
|
|
38
|
+
cx: xScale(accessor(d, x)) ?? null,
|
|
39
|
+
cy: yScale(accessor(d, y)) ?? null,
|
|
40
|
+
label: `(${accessor(d, x)}, ${accessor(d, y)})`
|
|
23
41
|
}))
|
|
24
42
|
.filter((p) => p.cx !== null && p.cy !== null)
|
|
25
43
|
})
|
package/src/Plot/Root.svelte
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
import { setContext, untrack } from 'svelte'
|
|
3
|
+
import type { Snippet } from 'svelte'
|
|
3
4
|
import { PlotState } from '../PlotState.svelte.js'
|
|
4
5
|
import { defaultPreset } from '../lib/preset.js'
|
|
5
6
|
|
|
7
|
+
type Margin = { top?: number; right?: number; bottom?: number; left?: number }
|
|
8
|
+
|
|
9
|
+
type Props = {
|
|
10
|
+
data?: Record<string, unknown>[]
|
|
11
|
+
x?: string
|
|
12
|
+
y?: string
|
|
13
|
+
color?: string
|
|
14
|
+
width?: number
|
|
15
|
+
height?: number
|
|
16
|
+
margin?: Margin
|
|
17
|
+
mode?: 'light' | 'dark'
|
|
18
|
+
children?: Snippet
|
|
19
|
+
}
|
|
20
|
+
|
|
6
21
|
let {
|
|
7
22
|
data = [],
|
|
8
23
|
x = undefined,
|
|
@@ -13,7 +28,7 @@
|
|
|
13
28
|
margin = undefined,
|
|
14
29
|
mode = 'light',
|
|
15
30
|
children
|
|
16
|
-
} = $props()
|
|
31
|
+
}: Props = $props()
|
|
17
32
|
|
|
18
33
|
const plotState = untrack(
|
|
19
34
|
() =>
|