@rokkit/chart 1.3.8 → 1.3.10
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/Chart.svelte +50 -64
- package/dist/Plot/Root.svelte +4 -1
- package/dist/Plot/Root.svelte.d.ts +2 -0
- package/dist/Plot/index.d.ts +1 -1
- package/dist/Plot/index.js +1 -1
- package/dist/Plot.svelte +4 -1
- package/dist/Plot.svelte.d.ts +2 -0
- package/dist/PlotState.svelte.d.ts +14 -2
- package/dist/PlotState.svelte.js +81 -5
- package/dist/charts/AreaChart.svelte +8 -1
- package/dist/charts/AreaChart.svelte.d.ts +5 -0
- package/dist/charts/BarChart.svelte +8 -1
- package/dist/charts/BarChart.svelte.d.ts +5 -0
- package/dist/charts/BoxPlot.svelte +3 -1
- package/dist/charts/BoxPlot.svelte.d.ts +1 -0
- package/dist/charts/BubbleChart.svelte +3 -1
- package/dist/charts/BubbleChart.svelte.d.ts +1 -0
- package/dist/charts/LineChart.svelte +3 -1
- package/dist/charts/LineChart.svelte.d.ts +1 -0
- package/dist/charts/PieChart.svelte +4 -2
- package/dist/charts/PieChart.svelte.d.ts +1 -0
- package/dist/charts/ScatterPlot.svelte +3 -1
- package/dist/charts/ScatterPlot.svelte.d.ts +1 -0
- package/dist/charts/ViolinPlot.svelte +3 -1
- package/dist/charts/ViolinPlot.svelte.d.ts +1 -0
- package/dist/geoms/Arc.svelte +21 -55
- package/dist/geoms/Arc.svelte.d.ts +4 -4
- package/dist/geoms/Area.svelte +45 -44
- package/dist/geoms/Area.svelte.d.ts +8 -1
- package/dist/geoms/Bar.svelte +33 -56
- package/dist/geoms/Bar.svelte.d.ts +9 -0
- package/dist/geoms/Box.svelte +118 -131
- package/dist/geoms/Box.svelte.d.ts +5 -3
- package/dist/geoms/Candlestick.svelte +22 -77
- package/dist/geoms/Candlestick.svelte.d.ts +2 -0
- package/dist/geoms/Heatmap.svelte +21 -66
- package/dist/geoms/Heatmap.svelte.d.ts +2 -0
- package/dist/geoms/Hexbin.svelte +20 -100
- package/dist/geoms/Hexbin.svelte.d.ts +2 -0
- package/dist/geoms/Jitter.svelte +21 -36
- package/dist/geoms/Jitter.svelte.d.ts +5 -3
- package/dist/geoms/Line.svelte +27 -31
- package/dist/geoms/Line.svelte.d.ts +5 -0
- package/dist/geoms/Point.svelte +31 -66
- package/dist/geoms/Point.svelte.d.ts +5 -1
- package/dist/geoms/Ribbon.svelte +30 -124
- package/dist/geoms/Ribbon.svelte.d.ts +2 -0
- package/dist/geoms/Rule.svelte +5 -1
- package/dist/geoms/Rule.svelte.d.ts +3 -0
- package/dist/geoms/Violin.svelte +21 -40
- package/dist/geoms/Violin.svelte.d.ts +5 -3
- package/dist/geoms/Waterfall.svelte +19 -80
- package/dist/geoms/Waterfall.svelte.d.ts +2 -0
- package/dist/geoms/lib/GeomState.svelte.d.ts +51 -0
- package/dist/geoms/lib/GeomState.svelte.js +79 -0
- package/dist/geoms/lib/aesthetics.d.ts +36 -0
- package/dist/geoms/lib/aesthetics.js +45 -0
- package/dist/geoms/lib/areas.d.ts +1 -1
- package/dist/geoms/lib/areas.js +18 -5
- package/dist/geoms/lib/bars.d.ts +2 -2
- package/dist/geoms/lib/bars.js +37 -17
- package/dist/geoms/lib/marks/arc.d.ts +24 -0
- package/dist/geoms/lib/marks/arc.js +28 -0
- package/dist/geoms/lib/marks/area.d.ts +23 -0
- package/dist/geoms/lib/marks/area.js +38 -0
- package/dist/geoms/lib/marks/bar.d.ts +16 -0
- package/dist/geoms/lib/marks/bar.js +43 -0
- package/dist/geoms/lib/marks/box.d.ts +14 -0
- package/dist/geoms/lib/marks/box.js +30 -0
- package/dist/geoms/lib/marks/candlestick.d.ts +27 -0
- package/dist/geoms/lib/marks/candlestick.js +52 -0
- package/dist/geoms/lib/marks/heatmap.d.ts +24 -0
- package/dist/geoms/lib/marks/heatmap.js +47 -0
- package/dist/geoms/lib/marks/hexbin.d.ts +29 -0
- package/dist/geoms/lib/marks/hexbin.js +62 -0
- package/dist/geoms/lib/marks/jitter.d.ts +21 -0
- package/dist/geoms/lib/marks/jitter.js +36 -0
- package/dist/geoms/lib/marks/line.d.ts +26 -0
- package/dist/geoms/lib/marks/line.js +25 -0
- package/dist/geoms/lib/marks/point.d.ts +25 -0
- package/dist/geoms/lib/marks/point.js +58 -0
- package/dist/geoms/lib/marks/ribbon.d.ts +32 -0
- package/dist/geoms/lib/marks/ribbon.js +80 -0
- package/dist/geoms/lib/marks/violin.d.ts +13 -0
- package/dist/geoms/lib/marks/violin.js +31 -0
- package/dist/geoms/lib/marks/waterfall.d.ts +25 -0
- package/dist/geoms/lib/marks/waterfall.js +58 -0
- package/dist/index.d.ts +1 -8
- package/dist/index.js +1 -8
- package/dist/lib/brewing/colors.d.ts +31 -1
- package/dist/lib/brewing/colors.js +34 -1
- package/dist/lib/brewing/marks/arcs.js +9 -4
- package/dist/lib/brewing/marks/boxes.js +8 -4
- package/dist/lib/brewing/marks/lines.js +13 -2
- package/dist/lib/brewing/marks/points.js +7 -2
- package/dist/lib/brewing/marks/swarm.js +6 -2
- package/dist/lib/brewing/marks/violins.js +8 -4
- package/dist/lib/preset.d.ts +11 -1
- package/dist/lib/preset.js +16 -4
- package/package.json +1 -1
- package/dist/Plot/Arc.svelte +0 -30
- package/dist/Plot/Arc.svelte.d.ts +0 -18
- package/dist/lib/brewer.d.ts +0 -9
- package/dist/lib/brewer.js +0 -25
- package/dist/lib/brewing/BoxBrewer.svelte.d.ts +0 -8
- package/dist/lib/brewing/BoxBrewer.svelte.js +0 -14
- package/dist/lib/brewing/CartesianBrewer.svelte.d.ts +0 -8
- package/dist/lib/brewing/CartesianBrewer.svelte.js +0 -21
- package/dist/lib/brewing/PieBrewer.svelte.d.ts +0 -8
- package/dist/lib/brewing/PieBrewer.svelte.js +0 -14
- package/dist/lib/brewing/QuartileBrewer.svelte.d.ts +0 -9
- package/dist/lib/brewing/QuartileBrewer.svelte.js +0 -51
- package/dist/lib/brewing/ViolinBrewer.svelte.d.ts +0 -8
- package/dist/lib/brewing/ViolinBrewer.svelte.js +0 -14
- package/dist/lib/brewing/axes.svelte.d.ts +0 -66
- package/dist/lib/brewing/axes.svelte.js +0 -270
- package/dist/lib/brewing/bars.svelte.d.ts +0 -56
- package/dist/lib/brewing/bars.svelte.js +0 -201
- package/dist/lib/brewing/brewer.svelte.d.ts +0 -124
- package/dist/lib/brewing/brewer.svelte.js +0 -277
- package/dist/lib/brewing/dimensions.svelte.d.ts +0 -35
- package/dist/lib/brewing/dimensions.svelte.js +0 -56
- package/dist/lib/brewing/index.svelte.d.ts +0 -118
- package/dist/lib/brewing/index.svelte.js +0 -205
- package/dist/lib/brewing/legends.svelte.d.ts +0 -48
- package/dist/lib/brewing/legends.svelte.js +0 -137
- package/dist/lib/brewing/marks/areas.d.ts +0 -31
- package/dist/lib/brewing/marks/areas.js +0 -72
- package/dist/lib/brewing/marks/bars.d.ts +0 -1
- package/dist/lib/brewing/marks/bars.js +0 -49
- package/dist/lib/brewing/scales.svelte.d.ts +0 -24
- package/dist/lib/brewing/scales.svelte.js +0 -82
- package/dist/lib/context.d.ts +0 -13
- package/dist/lib/context.js +0 -131
- package/dist/lib/plot/chartProps.d.ts +0 -177
- package/dist/lib/plot/chartProps.js +0 -76
- package/dist/lib/scales.svelte.d.ts +0 -35
- package/dist/lib/scales.svelte.js +0 -151
- package/dist/lib/ticks.d.ts +0 -36
- package/dist/lib/ticks.js +0 -46
package/dist/Chart.svelte
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { setContext } from 'svelte'
|
|
3
2
|
import type { Snippet } from 'svelte'
|
|
4
|
-
import
|
|
3
|
+
import Plot from './Plot.svelte'
|
|
5
4
|
import type { ChartSpec } from './spec/chart-spec.js'
|
|
6
|
-
|
|
7
|
-
type Channels = {
|
|
8
|
-
x?: string
|
|
9
|
-
y?: string
|
|
10
|
-
color?: string
|
|
11
|
-
pattern?: string
|
|
12
|
-
fill?: string
|
|
13
|
-
size?: string
|
|
14
|
-
label?: string
|
|
15
|
-
symbol?: string
|
|
16
|
-
}
|
|
5
|
+
import type { PlotSpec, GeomSpec } from './lib/plot/types.js'
|
|
17
6
|
|
|
18
7
|
type Props = {
|
|
19
8
|
spec?: ChartSpec
|
|
@@ -49,59 +38,56 @@
|
|
|
49
38
|
children
|
|
50
39
|
}: Props = $props()
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (y) channels.y = y
|
|
59
|
-
if (color) channels.color = color
|
|
60
|
-
if (pattern) channels.pattern = pattern
|
|
61
|
-
if (fill) channels.fill = fill
|
|
62
|
-
if (size) channels.size = size
|
|
63
|
-
if (label) channels.label = label
|
|
64
|
-
if (symbol) channels.symbol = symbol
|
|
65
|
-
return channels
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
$effect(() => {
|
|
41
|
+
// `Chart` is a thin wrapper over the geom-path host (`Plot`). It maps the fluent
|
|
42
|
+
// `ChartSpec` builder (data / channels / layers / options) onto a `PlotSpec` and renders
|
|
43
|
+
// the layers as geoms. Axes/grid stay off by default — `Chart` historically rendered just
|
|
44
|
+
// the marks (plus any declarative geom children). See the brewer-consolidation spec
|
|
45
|
+
// (docs/backlog/2026-08-17-chart-aesthetics-unification.md §9).
|
|
46
|
+
const plotSpec = $derived.by((): PlotSpec => {
|
|
69
47
|
if (spec) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
48
|
+
const ch = (spec.channels ?? {}) as {
|
|
49
|
+
x?: string
|
|
50
|
+
y?: string
|
|
51
|
+
color?: string
|
|
52
|
+
pattern?: string
|
|
53
|
+
}
|
|
54
|
+
const opts = (spec.options ?? {}) as {
|
|
55
|
+
width?: number
|
|
56
|
+
height?: number
|
|
57
|
+
grid?: unknown
|
|
58
|
+
legend?: unknown
|
|
59
|
+
}
|
|
60
|
+
const layers = (spec.layers ?? []) as GeomSpec[]
|
|
61
|
+
return {
|
|
62
|
+
data: spec.data as Record<string, unknown>[],
|
|
63
|
+
x: ch.x,
|
|
64
|
+
y: ch.y,
|
|
65
|
+
color: ch.color,
|
|
66
|
+
pattern: ch.pattern,
|
|
67
|
+
width: opts.width ?? width,
|
|
68
|
+
height: opts.height ?? height,
|
|
69
|
+
grid: 'grid' in opts,
|
|
70
|
+
legend: 'legend' in opts,
|
|
71
|
+
geoms: layers.map((l) => ({ pattern: ch.pattern, ...l }))
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
data,
|
|
76
|
+
x,
|
|
77
|
+
y,
|
|
78
|
+
color: color ?? fill,
|
|
79
|
+
pattern,
|
|
80
|
+
size,
|
|
81
|
+
symbol,
|
|
82
|
+
width,
|
|
83
|
+
height,
|
|
84
|
+
grid: false,
|
|
85
|
+
legend: false,
|
|
86
|
+
geoms: []
|
|
80
87
|
}
|
|
81
88
|
})
|
|
82
89
|
</script>
|
|
83
90
|
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
{@render children?.()}
|
|
88
|
-
</g>
|
|
89
|
-
</svg>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<style>
|
|
93
|
-
.chart-container {
|
|
94
|
-
position: relative;
|
|
95
|
-
width: 100%;
|
|
96
|
-
height: auto;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
svg {
|
|
100
|
-
display: block;
|
|
101
|
-
overflow: visible;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.chart-area {
|
|
105
|
-
pointer-events: all;
|
|
106
|
-
}
|
|
107
|
-
</style>
|
|
91
|
+
<Plot spec={plotSpec} axes={false} label={label ?? false} {mode}>
|
|
92
|
+
{@render children?.()}
|
|
93
|
+
</Plot>
|
package/dist/Plot/Root.svelte
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
x?: string
|
|
12
12
|
y?: string
|
|
13
13
|
color?: string
|
|
14
|
+
/** Interior aesthetic default (field); geoms inherit unless they set their own. */
|
|
15
|
+
fill?: string
|
|
14
16
|
width?: number
|
|
15
17
|
height?: number
|
|
16
18
|
margin?: Margin
|
|
@@ -47,6 +49,7 @@
|
|
|
47
49
|
x = undefined,
|
|
48
50
|
y = undefined,
|
|
49
51
|
color = undefined,
|
|
52
|
+
fill = undefined,
|
|
50
53
|
width = 600,
|
|
51
54
|
height = 400,
|
|
52
55
|
margin = undefined,
|
|
@@ -71,7 +74,7 @@
|
|
|
71
74
|
// The composable root is just PlotSurface (the shared shell) fed a config from these props.
|
|
72
75
|
const config = $derived({
|
|
73
76
|
data,
|
|
74
|
-
channels: { x, y, color },
|
|
77
|
+
channels: { x, y, color, fill },
|
|
75
78
|
width,
|
|
76
79
|
height,
|
|
77
80
|
margin,
|
package/dist/Plot/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { default as Grid } from "./Grid.svelte";
|
|
|
6
6
|
export { default as Line } from "../geoms/Line.svelte";
|
|
7
7
|
export { default as Area } from "../geoms/Area.svelte";
|
|
8
8
|
export { default as Point } from "../geoms/Point.svelte";
|
|
9
|
-
export { default as Arc } from "
|
|
9
|
+
export { default as Arc } from "../geoms/Arc.svelte";
|
package/dist/Plot/index.js
CHANGED
|
@@ -6,4 +6,4 @@ export { default as Grid } from './Grid.svelte'
|
|
|
6
6
|
export { default as Line } from '../geoms/Line.svelte'
|
|
7
7
|
export { default as Area } from '../geoms/Area.svelte'
|
|
8
8
|
export { default as Point } from '../geoms/Point.svelte'
|
|
9
|
-
export { default as Arc } from '
|
|
9
|
+
export { default as Arc } from '../geoms/Arc.svelte'
|
package/dist/Plot.svelte
CHANGED
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
summary?: string
|
|
44
44
|
tooltip?: boolean | ((data: Row) => string)
|
|
45
45
|
zoom?: boolean
|
|
46
|
+
/** Force chart direction (else inferred). Also settable via `spec.orientation`. */
|
|
47
|
+
orientation?: 'horizontal' | 'vertical'
|
|
46
48
|
xFormat?: (v: unknown) => string
|
|
47
49
|
yFormat?: (v: unknown) => string
|
|
48
50
|
xTicks?: number
|
|
@@ -78,6 +80,7 @@
|
|
|
78
80
|
summary = '',
|
|
79
81
|
tooltip = false,
|
|
80
82
|
zoom = false,
|
|
83
|
+
orientation = undefined,
|
|
81
84
|
xFormat = undefined,
|
|
82
85
|
yFormat = undefined,
|
|
83
86
|
xTicks = undefined,
|
|
@@ -138,7 +141,7 @@
|
|
|
138
141
|
colorScale: spec?.colorScale,
|
|
139
142
|
colorScheme: spec?.colorScheme,
|
|
140
143
|
colorMidpoint: spec?.colorMidpoint,
|
|
141
|
-
orientation: spec?.orientation,
|
|
144
|
+
orientation: orientation ?? spec?.orientation,
|
|
142
145
|
sort: spec?.sort,
|
|
143
146
|
continuousCategory: spec?.continuousCategory,
|
|
144
147
|
chartPreset,
|
package/dist/Plot.svelte.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ type Props = {
|
|
|
26
26
|
summary?: string;
|
|
27
27
|
tooltip?: boolean | ((data: Row) => string);
|
|
28
28
|
zoom?: boolean;
|
|
29
|
+
/** Force chart direction (else inferred). Also settable via `spec.orientation`. */
|
|
30
|
+
orientation?: 'horizontal' | 'vertical';
|
|
29
31
|
xFormat?: (v: unknown) => string;
|
|
30
32
|
yFormat?: (v: unknown) => string;
|
|
31
33
|
xTicks?: number;
|
|
@@ -21,6 +21,7 @@ export class PlotState {
|
|
|
21
21
|
patterns: Map<unknown, string> | SvelteMap<any, any>;
|
|
22
22
|
symbols: Map<unknown, string> | SvelteMap<any, any>;
|
|
23
23
|
colorField: any;
|
|
24
|
+
fillField: any;
|
|
24
25
|
patternField: any;
|
|
25
26
|
symbolField: any;
|
|
26
27
|
geomTypes: SvelteSet<any>;
|
|
@@ -41,11 +42,12 @@ export class PlotState {
|
|
|
41
42
|
symbols: any;
|
|
42
43
|
};
|
|
43
44
|
get data(): any[];
|
|
44
|
-
/** @returns {{ x?: string, y?: string, color?: string, pattern?: string, symbol?: string }} */
|
|
45
|
+
/** @returns {{ x?: string, y?: string, color?: string, fill?: string, pattern?: string, symbol?: string }} */
|
|
45
46
|
get channels(): {
|
|
46
47
|
x?: string;
|
|
47
48
|
y?: string;
|
|
48
49
|
color?: string;
|
|
50
|
+
fill?: string;
|
|
49
51
|
pattern?: string;
|
|
50
52
|
symbol?: string;
|
|
51
53
|
};
|
|
@@ -80,9 +82,19 @@ export class PlotState {
|
|
|
80
82
|
};
|
|
81
83
|
opacity: {
|
|
82
84
|
area: number;
|
|
85
|
+
bar: number;
|
|
86
|
+
line: number;
|
|
87
|
+
point: number;
|
|
88
|
+
arc: number;
|
|
83
89
|
box: number;
|
|
84
90
|
violin: number;
|
|
85
|
-
|
|
91
|
+
jitter: number;
|
|
92
|
+
heatmap: number;
|
|
93
|
+
candlestick: number;
|
|
94
|
+
hexbin: number;
|
|
95
|
+
ribbon: number;
|
|
96
|
+
waterfall: number;
|
|
97
|
+
rule: number;
|
|
86
98
|
};
|
|
87
99
|
patterns: string[];
|
|
88
100
|
symbols: string[];
|
package/dist/PlotState.svelte.js
CHANGED
|
@@ -73,11 +73,40 @@ export class PlotState {
|
|
|
73
73
|
x: tc.x ?? geom.channels?.x,
|
|
74
74
|
y: tc.y ?? geom.channels?.y,
|
|
75
75
|
color: tc.color ?? geom.channels?.color,
|
|
76
|
+
fill: tc.fill ?? geom.channels?.fill,
|
|
76
77
|
pattern: tc.pattern ?? geom.channels?.pattern,
|
|
77
78
|
symbol: tc.symbol ?? geom.channels?.symbol
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
// Field names feeding the shared categorical color scale: the `color` AND `fill` channels,
|
|
83
|
+
// from the top-level channels and EVERY geom (union, de-duped, order-preserving). Literal
|
|
84
|
+
// CSS colors are excluded. One palette/legend spans both aesthetics — the "shared scale"
|
|
85
|
+
// model (see docs/backlog/2026-08-17-chart-aesthetics-unification.md §2).
|
|
86
|
+
#sharedColorValues() {
|
|
87
|
+
const fields = []
|
|
88
|
+
const addField = (f) => {
|
|
89
|
+
if (f && !isLiteralColor(f) && !fields.includes(f)) fields.push(f)
|
|
90
|
+
}
|
|
91
|
+
addField(this.#channels.color)
|
|
92
|
+
addField(this.#channels.fill)
|
|
93
|
+
for (const g of this.#geoms) {
|
|
94
|
+
addField(g.channels?.color)
|
|
95
|
+
addField(g.channels?.fill)
|
|
96
|
+
}
|
|
97
|
+
const seen = new Set()
|
|
98
|
+
const values = []
|
|
99
|
+
for (const f of fields) {
|
|
100
|
+
for (const v of distinct(this.#data, f)) {
|
|
101
|
+
if (!seen.has(v)) {
|
|
102
|
+
seen.add(v)
|
|
103
|
+
values.push(v)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return values
|
|
108
|
+
}
|
|
109
|
+
|
|
81
110
|
#effectiveChannels = $derived.by(() => {
|
|
82
111
|
const tc = this.#channels
|
|
83
112
|
const firstGeom = this.#geoms[0]
|
|
@@ -210,8 +239,12 @@ export class PlotState {
|
|
|
210
239
|
|
|
211
240
|
// For stacked bars, compute y domain from per-x column totals.
|
|
212
241
|
#resolveStackDomain(field) {
|
|
213
|
-
const stackGeom = this.#geoms.find(
|
|
242
|
+
const stackGeom = this.#geoms.find(
|
|
243
|
+
(g) => g.options?.stack || g.options?.position === 'stack' || g.options?.position === 'fill'
|
|
244
|
+
)
|
|
214
245
|
if (!stackGeom) return null
|
|
246
|
+
// position='fill' normalizes each column to 100% → the value domain is [0,1].
|
|
247
|
+
if (stackGeom.options?.position === 'fill') return [0, 1]
|
|
215
248
|
const xField = this.#effectiveChannels.x
|
|
216
249
|
const stackData = this.geomData(stackGeom.id)
|
|
217
250
|
if (!xField || stackData.length === 0) return null
|
|
@@ -221,8 +254,18 @@ export class PlotState {
|
|
|
221
254
|
const colorField = isLiteralColor(this.#effectiveChannels.color)
|
|
222
255
|
? null
|
|
223
256
|
: this.#effectiveChannels.color
|
|
257
|
+
const fillField = isLiteralColor(this.#effectiveChannels.fill)
|
|
258
|
+
? null
|
|
259
|
+
: this.#effectiveChannels.fill
|
|
224
260
|
const patternField = this.#effectiveChannels.pattern
|
|
225
|
-
|
|
261
|
+
// Mirror buildStackedBars/subBandFields (group=fill first, then color, then pattern).
|
|
262
|
+
const stackField =
|
|
263
|
+
[fillField, colorField, patternField].find((f) => f && f !== xField) ?? (fillField ?? colorField)
|
|
264
|
+
// No grouping field → buildStackedBars falls back to buildBars (individual bars, no
|
|
265
|
+
// actual stacking), so there's no stacked total to size to. Bail to the normal value
|
|
266
|
+
// extent; otherwise every row collapses to the same cKey below and the lookup's set()
|
|
267
|
+
// overwrites, shrinking the domain to the last row per x — and the bars overflow.
|
|
268
|
+
if (!stackField) return null
|
|
226
269
|
const lookup = new SvelteMap()
|
|
227
270
|
for (const d of stackData) {
|
|
228
271
|
const xVal = d[xField]
|
|
@@ -240,6 +283,31 @@ export class PlotState {
|
|
|
240
283
|
return [0, Math.max(0, ...totals.values())]
|
|
241
284
|
}
|
|
242
285
|
|
|
286
|
+
// Waterfall bars sit at the RUNNING TOTAL, not the per-step value — so the y-domain must
|
|
287
|
+
// span the cumulative range, else bars overflow the axis. Mirrors buildWaterfallMarks.
|
|
288
|
+
#resolveWaterfallDomain(field) {
|
|
289
|
+
const geom = this.#geoms.find((g) => g.type === 'waterfall')
|
|
290
|
+
if (!geom) return null
|
|
291
|
+
const data = this.geomData(geom.id)
|
|
292
|
+
if (data.length === 0) return null
|
|
293
|
+
const totalField = geom.options?.totalField
|
|
294
|
+
let cumulative = 0
|
|
295
|
+
let min = 0
|
|
296
|
+
let max = 0
|
|
297
|
+
for (const d of data) {
|
|
298
|
+
if (totalField && d[totalField]) {
|
|
299
|
+
min = Math.min(min, 0, cumulative)
|
|
300
|
+
max = Math.max(max, 0, cumulative)
|
|
301
|
+
} else {
|
|
302
|
+
const start = cumulative
|
|
303
|
+
cumulative += Number(d[field]) || 0
|
|
304
|
+
min = Math.min(min, start, cumulative)
|
|
305
|
+
max = Math.max(max, start, cumulative)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return [min, max]
|
|
309
|
+
}
|
|
310
|
+
|
|
243
311
|
yScale = $derived.by(() => {
|
|
244
312
|
const field = this.#effectiveChannels.y
|
|
245
313
|
if (!field) return null
|
|
@@ -248,7 +316,11 @@ export class PlotState {
|
|
|
248
316
|
// includeZero applies to the VALUE axis: vertical charts (value on y) and flipped
|
|
249
317
|
// charts (value still y, but now the horizontal screen axis) both want a 0 baseline.
|
|
250
318
|
const includeZero = this.orientation === 'vertical' || this.#flipped
|
|
251
|
-
const yDomain =
|
|
319
|
+
const yDomain =
|
|
320
|
+
this.#yDomain ??
|
|
321
|
+
this.#resolveBoxDomain() ??
|
|
322
|
+
this.#resolveStackDomain(field) ??
|
|
323
|
+
this.#resolveWaterfallDomain(field)
|
|
252
324
|
// Flip: the value (y) axis runs along the horizontal screen → range over width.
|
|
253
325
|
const range = this.#flipped ? [0, this.#innerWidth] : undefined
|
|
254
326
|
const base = buildUnifiedYScale(datasets, field, this.#innerHeight, { domain: yDomain, includeZero, range })
|
|
@@ -268,7 +340,7 @@ export class PlotState {
|
|
|
268
340
|
const literal = new Map([[null, { fill: field, stroke: field }]])
|
|
269
341
|
return literal
|
|
270
342
|
}
|
|
271
|
-
const values = this.#colorDomain ??
|
|
343
|
+
const values = this.#colorDomain ?? this.#sharedColorValues()
|
|
272
344
|
// No color channel but data exists → use first preset color for single-series rendering.
|
|
273
345
|
// This prevents geoms from falling back to gray (#888) on charts with no fill channel.
|
|
274
346
|
if (values.length === 0 && this.#data.length > 0) return assignColors([null], this.#mode, this.#chartPreset)
|
|
@@ -296,6 +368,10 @@ export class PlotState {
|
|
|
296
368
|
colorField = $derived(
|
|
297
369
|
isLiteralColor(this.#effectiveChannels.color) ? null : this.#effectiveChannels.color
|
|
298
370
|
)
|
|
371
|
+
// Fill field (interior aesthetic), parallel to colorField. Null for a literal CSS color.
|
|
372
|
+
fillField = $derived(
|
|
373
|
+
isLiteralColor(this.#effectiveChannels.fill) ? null : this.#effectiveChannels.fill
|
|
374
|
+
)
|
|
299
375
|
patternField = $derived(this.#effectiveChannels.pattern)
|
|
300
376
|
symbolField = $derived(this.#effectiveChannels.symbol)
|
|
301
377
|
|
|
@@ -432,7 +508,7 @@ export class PlotState {
|
|
|
432
508
|
// array separately, so their elements are not ===. Same content, aligned identity.
|
|
433
509
|
return this.#rawData
|
|
434
510
|
}
|
|
435
|
-
/** @returns {{ x?: string, y?: string, color?: string, pattern?: string, symbol?: string }} */
|
|
511
|
+
/** @returns {{ x?: string, y?: string, color?: string, fill?: string, pattern?: string, symbol?: string }} */
|
|
436
512
|
get channels() {
|
|
437
513
|
return this.#channels
|
|
438
514
|
}
|
|
@@ -14,7 +14,12 @@
|
|
|
14
14
|
stat?: string
|
|
15
15
|
curve?: 'linear' | 'smooth' | 'step'
|
|
16
16
|
pattern?: string
|
|
17
|
+
/** @deprecated use `position="stack"`. */
|
|
17
18
|
stack?: boolean
|
|
19
|
+
/** Multi-series arrangement: 'stack' | 'fill' | 'identity' (default). */
|
|
20
|
+
position?: 'stack' | 'fill' | 'identity'
|
|
21
|
+
/** Fixed area opacity 0–1. */
|
|
22
|
+
alpha?: number
|
|
18
23
|
width?: number
|
|
19
24
|
height?: number
|
|
20
25
|
mode?: 'light' | 'dark'
|
|
@@ -42,6 +47,8 @@
|
|
|
42
47
|
curve = undefined,
|
|
43
48
|
pattern = undefined,
|
|
44
49
|
stack = false,
|
|
50
|
+
position = undefined,
|
|
51
|
+
alpha = undefined,
|
|
45
52
|
width = 600,
|
|
46
53
|
height = 400,
|
|
47
54
|
mode = undefined,
|
|
@@ -82,5 +89,5 @@
|
|
|
82
89
|
{selectable}
|
|
83
90
|
bind:selected
|
|
84
91
|
>
|
|
85
|
-
<Area {x} {y} color={fill} {pattern} {stat} options={{ curve, stack }} />
|
|
92
|
+
<Area {x} {y} color={fill} {pattern} {stat} {position} {alpha} options={{ curve, stack }} />
|
|
86
93
|
</Plot>
|
|
@@ -12,7 +12,12 @@ type Props = {
|
|
|
12
12
|
stat?: string;
|
|
13
13
|
curve?: 'linear' | 'smooth' | 'step';
|
|
14
14
|
pattern?: string;
|
|
15
|
+
/** @deprecated use `position="stack"`. */
|
|
15
16
|
stack?: boolean;
|
|
17
|
+
/** Multi-series arrangement: 'stack' | 'fill' | 'identity' (default). */
|
|
18
|
+
position?: 'stack' | 'fill' | 'identity';
|
|
19
|
+
/** Fixed area opacity 0–1. */
|
|
20
|
+
alpha?: number;
|
|
16
21
|
width?: number;
|
|
17
22
|
height?: number;
|
|
18
23
|
mode?: 'light' | 'dark';
|
|
@@ -18,7 +18,12 @@
|
|
|
18
18
|
grid?: boolean
|
|
19
19
|
legend?: boolean
|
|
20
20
|
stat?: string
|
|
21
|
+
/** @deprecated use `position="stack"`. */
|
|
21
22
|
stack?: boolean
|
|
23
|
+
/** Multi-series arrangement: 'stack' | 'dodge' (default) | 'fill' | 'identity'. */
|
|
24
|
+
position?: 'stack' | 'dodge' | 'fill' | 'identity'
|
|
25
|
+
/** Fixed bar opacity 0–1. */
|
|
26
|
+
alpha?: number
|
|
22
27
|
label?: boolean | string | ((data: Row) => unknown)
|
|
23
28
|
tooltip?: boolean | ((data: Row) => string)
|
|
24
29
|
highlight?: 'first' | 'last' | 'min' | 'max' | number | ((row: Row, i: number) => boolean)
|
|
@@ -46,6 +51,8 @@
|
|
|
46
51
|
legend = false,
|
|
47
52
|
stat = 'identity',
|
|
48
53
|
stack = false,
|
|
54
|
+
position = undefined,
|
|
55
|
+
alpha = undefined,
|
|
49
56
|
label = false,
|
|
50
57
|
tooltip = false,
|
|
51
58
|
highlight = undefined,
|
|
@@ -80,5 +87,5 @@
|
|
|
80
87
|
{selectable}
|
|
81
88
|
bind:selected
|
|
82
89
|
>
|
|
83
|
-
<Bar {x} {y} color={fill} {pattern} {label} {stat} options={{ stack }} />
|
|
90
|
+
<Bar {x} {y} color={fill} {pattern} {label} {stat} {position} {alpha} options={{ stack }} />
|
|
84
91
|
</Plot>
|
|
@@ -16,7 +16,12 @@ type Props = {
|
|
|
16
16
|
grid?: boolean;
|
|
17
17
|
legend?: boolean;
|
|
18
18
|
stat?: string;
|
|
19
|
+
/** @deprecated use `position="stack"`. */
|
|
19
20
|
stack?: boolean;
|
|
21
|
+
/** Multi-series arrangement: 'stack' | 'dodge' (default) | 'fill' | 'identity'. */
|
|
22
|
+
position?: 'stack' | 'dodge' | 'fill' | 'identity';
|
|
23
|
+
/** Fixed bar opacity 0–1. */
|
|
24
|
+
alpha?: number;
|
|
20
25
|
label?: boolean | string | ((data: Row) => unknown);
|
|
21
26
|
tooltip?: boolean | ((data: Row) => string);
|
|
22
27
|
highlight?: 'first' | 'last' | 'min' | 'max' | number | ((row: Row, i: number) => boolean);
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
x?: string
|
|
10
10
|
y?: string
|
|
11
11
|
fill?: string
|
|
12
|
+
alpha?: number
|
|
12
13
|
width?: number
|
|
13
14
|
height?: number
|
|
14
15
|
mode?: 'light' | 'dark'
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
x = undefined,
|
|
26
27
|
y = undefined,
|
|
27
28
|
fill = undefined,
|
|
29
|
+
alpha = undefined,
|
|
28
30
|
width = 600,
|
|
29
31
|
height = 400,
|
|
30
32
|
mode = undefined,
|
|
@@ -38,5 +40,5 @@
|
|
|
38
40
|
</script>
|
|
39
41
|
|
|
40
42
|
<Plot {data} {width} {height} {mode} {grid} {legend} {tooltip} {yFormat} {yTicks} {minorTicks}>
|
|
41
|
-
<Box {x} {y} {fill} />
|
|
43
|
+
<Box {x} {y} {fill} {alpha} />
|
|
42
44
|
</Plot>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
color?: string
|
|
14
14
|
symbol?: string
|
|
15
15
|
size?: string
|
|
16
|
+
alpha?: number
|
|
16
17
|
width?: number
|
|
17
18
|
height?: number
|
|
18
19
|
mode?: 'light' | 'dark'
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
color = undefined,
|
|
39
40
|
symbol: _symbol = undefined,
|
|
40
41
|
size, // required: field name for bubble radius
|
|
42
|
+
alpha = undefined,
|
|
41
43
|
width = 600,
|
|
42
44
|
height = 400,
|
|
43
45
|
mode = undefined,
|
|
@@ -76,5 +78,5 @@
|
|
|
76
78
|
{selectable}
|
|
77
79
|
bind:selected
|
|
78
80
|
>
|
|
79
|
-
<Point {x} {y} {color} {size} />
|
|
81
|
+
<Point {x} {y} {color} {size} {alpha} />
|
|
80
82
|
</Plot>
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
y?: string
|
|
13
13
|
color?: string
|
|
14
14
|
stat?: string
|
|
15
|
+
alpha?: number
|
|
15
16
|
symbol?: string
|
|
16
17
|
curve?: 'linear' | 'smooth' | 'step'
|
|
17
18
|
label?: boolean | string | ((data: Row) => unknown)
|
|
@@ -39,6 +40,7 @@
|
|
|
39
40
|
y = undefined,
|
|
40
41
|
color = undefined,
|
|
41
42
|
stat = 'identity',
|
|
43
|
+
alpha = undefined,
|
|
42
44
|
symbol = undefined,
|
|
43
45
|
curve = undefined, // forwarded to Line options
|
|
44
46
|
label = false,
|
|
@@ -82,5 +84,5 @@
|
|
|
82
84
|
{selectable}
|
|
83
85
|
bind:selected
|
|
84
86
|
>
|
|
85
|
-
<Line {x} {y} {color} {symbol} {label} {stat} options={{ curve }} />
|
|
87
|
+
<Line {x} {y} {color} {symbol} {label} {stat} {alpha} options={{ curve }} />
|
|
86
88
|
</Plot>
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
mode?: 'light' | 'dark'
|
|
19
19
|
legend?: boolean
|
|
20
20
|
stat?: string
|
|
21
|
+
alpha?: number
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
let {
|
|
@@ -33,7 +34,8 @@
|
|
|
33
34
|
height = 400,
|
|
34
35
|
mode = undefined,
|
|
35
36
|
legend = false,
|
|
36
|
-
stat = 'sum'
|
|
37
|
+
stat = 'sum',
|
|
38
|
+
alpha = undefined
|
|
37
39
|
}: Props = $props()
|
|
38
40
|
</script>
|
|
39
41
|
|
|
@@ -48,5 +50,5 @@
|
|
|
48
50
|
{legend}
|
|
49
51
|
{tooltip}
|
|
50
52
|
>
|
|
51
|
-
<Arc theta={y} fill={label ?? fill} {pattern} {labelFn} {stat} options={{ innerRadius }} />
|
|
53
|
+
<Arc theta={y} fill={label ?? fill} {pattern} {labelFn} {stat} {alpha} options={{ innerRadius }} />
|
|
52
54
|
</Plot>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
color?: string
|
|
14
14
|
symbol?: string
|
|
15
15
|
size?: string
|
|
16
|
+
alpha?: number
|
|
16
17
|
label?: boolean | string | ((data: Row) => unknown)
|
|
17
18
|
tooltip?: boolean | ((data: Row) => string)
|
|
18
19
|
width?: number
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
color = undefined,
|
|
41
42
|
symbol = undefined,
|
|
42
43
|
size = undefined,
|
|
44
|
+
alpha = undefined,
|
|
43
45
|
label = false,
|
|
44
46
|
tooltip = false,
|
|
45
47
|
width = 600,
|
|
@@ -80,5 +82,5 @@
|
|
|
80
82
|
{selectable}
|
|
81
83
|
bind:selected
|
|
82
84
|
>
|
|
83
|
-
<Point {x} {y} {color} {size} {symbol} {label} options={{ jitter }} />
|
|
85
|
+
<Point {x} {y} {color} {size} {symbol} {label} {alpha} options={{ jitter }} />
|
|
84
86
|
</Plot>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
x?: string
|
|
10
10
|
y?: string
|
|
11
11
|
fill?: string
|
|
12
|
+
alpha?: number
|
|
12
13
|
width?: number
|
|
13
14
|
height?: number
|
|
14
15
|
mode?: 'light' | 'dark'
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
x = undefined,
|
|
26
27
|
y = undefined,
|
|
27
28
|
fill = undefined,
|
|
29
|
+
alpha = undefined,
|
|
28
30
|
width = 600,
|
|
29
31
|
height = 400,
|
|
30
32
|
mode = undefined,
|
|
@@ -38,5 +40,5 @@
|
|
|
38
40
|
</script>
|
|
39
41
|
|
|
40
42
|
<Plot {data} {width} {height} {mode} {grid} {legend} {tooltip} {yFormat} {yTicks} {minorTicks}>
|
|
41
|
-
<Violin {x} {y} {fill} />
|
|
43
|
+
<Violin {x} {y} {fill} {alpha} />
|
|
42
44
|
</Plot>
|