@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.
Files changed (140) hide show
  1. package/dist/Chart.svelte +50 -64
  2. package/dist/Plot/Root.svelte +4 -1
  3. package/dist/Plot/Root.svelte.d.ts +2 -0
  4. package/dist/Plot/index.d.ts +1 -1
  5. package/dist/Plot/index.js +1 -1
  6. package/dist/Plot.svelte +4 -1
  7. package/dist/Plot.svelte.d.ts +2 -0
  8. package/dist/PlotState.svelte.d.ts +14 -2
  9. package/dist/PlotState.svelte.js +81 -5
  10. package/dist/charts/AreaChart.svelte +8 -1
  11. package/dist/charts/AreaChart.svelte.d.ts +5 -0
  12. package/dist/charts/BarChart.svelte +8 -1
  13. package/dist/charts/BarChart.svelte.d.ts +5 -0
  14. package/dist/charts/BoxPlot.svelte +3 -1
  15. package/dist/charts/BoxPlot.svelte.d.ts +1 -0
  16. package/dist/charts/BubbleChart.svelte +3 -1
  17. package/dist/charts/BubbleChart.svelte.d.ts +1 -0
  18. package/dist/charts/LineChart.svelte +3 -1
  19. package/dist/charts/LineChart.svelte.d.ts +1 -0
  20. package/dist/charts/PieChart.svelte +4 -2
  21. package/dist/charts/PieChart.svelte.d.ts +1 -0
  22. package/dist/charts/ScatterPlot.svelte +3 -1
  23. package/dist/charts/ScatterPlot.svelte.d.ts +1 -0
  24. package/dist/charts/ViolinPlot.svelte +3 -1
  25. package/dist/charts/ViolinPlot.svelte.d.ts +1 -0
  26. package/dist/geoms/Arc.svelte +21 -55
  27. package/dist/geoms/Arc.svelte.d.ts +4 -4
  28. package/dist/geoms/Area.svelte +45 -44
  29. package/dist/geoms/Area.svelte.d.ts +8 -1
  30. package/dist/geoms/Bar.svelte +33 -56
  31. package/dist/geoms/Bar.svelte.d.ts +9 -0
  32. package/dist/geoms/Box.svelte +118 -131
  33. package/dist/geoms/Box.svelte.d.ts +5 -3
  34. package/dist/geoms/Candlestick.svelte +22 -77
  35. package/dist/geoms/Candlestick.svelte.d.ts +2 -0
  36. package/dist/geoms/Heatmap.svelte +21 -66
  37. package/dist/geoms/Heatmap.svelte.d.ts +2 -0
  38. package/dist/geoms/Hexbin.svelte +20 -100
  39. package/dist/geoms/Hexbin.svelte.d.ts +2 -0
  40. package/dist/geoms/Jitter.svelte +21 -36
  41. package/dist/geoms/Jitter.svelte.d.ts +5 -3
  42. package/dist/geoms/Line.svelte +27 -31
  43. package/dist/geoms/Line.svelte.d.ts +5 -0
  44. package/dist/geoms/Point.svelte +31 -66
  45. package/dist/geoms/Point.svelte.d.ts +5 -1
  46. package/dist/geoms/Ribbon.svelte +30 -124
  47. package/dist/geoms/Ribbon.svelte.d.ts +2 -0
  48. package/dist/geoms/Rule.svelte +5 -1
  49. package/dist/geoms/Rule.svelte.d.ts +3 -0
  50. package/dist/geoms/Violin.svelte +21 -40
  51. package/dist/geoms/Violin.svelte.d.ts +5 -3
  52. package/dist/geoms/Waterfall.svelte +19 -80
  53. package/dist/geoms/Waterfall.svelte.d.ts +2 -0
  54. package/dist/geoms/lib/GeomState.svelte.d.ts +51 -0
  55. package/dist/geoms/lib/GeomState.svelte.js +79 -0
  56. package/dist/geoms/lib/aesthetics.d.ts +36 -0
  57. package/dist/geoms/lib/aesthetics.js +45 -0
  58. package/dist/geoms/lib/areas.d.ts +1 -1
  59. package/dist/geoms/lib/areas.js +18 -5
  60. package/dist/geoms/lib/bars.d.ts +2 -2
  61. package/dist/geoms/lib/bars.js +37 -17
  62. package/dist/geoms/lib/marks/arc.d.ts +24 -0
  63. package/dist/geoms/lib/marks/arc.js +28 -0
  64. package/dist/geoms/lib/marks/area.d.ts +23 -0
  65. package/dist/geoms/lib/marks/area.js +38 -0
  66. package/dist/geoms/lib/marks/bar.d.ts +16 -0
  67. package/dist/geoms/lib/marks/bar.js +43 -0
  68. package/dist/geoms/lib/marks/box.d.ts +14 -0
  69. package/dist/geoms/lib/marks/box.js +30 -0
  70. package/dist/geoms/lib/marks/candlestick.d.ts +27 -0
  71. package/dist/geoms/lib/marks/candlestick.js +52 -0
  72. package/dist/geoms/lib/marks/heatmap.d.ts +24 -0
  73. package/dist/geoms/lib/marks/heatmap.js +47 -0
  74. package/dist/geoms/lib/marks/hexbin.d.ts +29 -0
  75. package/dist/geoms/lib/marks/hexbin.js +62 -0
  76. package/dist/geoms/lib/marks/jitter.d.ts +21 -0
  77. package/dist/geoms/lib/marks/jitter.js +36 -0
  78. package/dist/geoms/lib/marks/line.d.ts +26 -0
  79. package/dist/geoms/lib/marks/line.js +25 -0
  80. package/dist/geoms/lib/marks/point.d.ts +25 -0
  81. package/dist/geoms/lib/marks/point.js +58 -0
  82. package/dist/geoms/lib/marks/ribbon.d.ts +32 -0
  83. package/dist/geoms/lib/marks/ribbon.js +80 -0
  84. package/dist/geoms/lib/marks/violin.d.ts +13 -0
  85. package/dist/geoms/lib/marks/violin.js +31 -0
  86. package/dist/geoms/lib/marks/waterfall.d.ts +25 -0
  87. package/dist/geoms/lib/marks/waterfall.js +58 -0
  88. package/dist/index.d.ts +1 -8
  89. package/dist/index.js +1 -8
  90. package/dist/lib/brewing/colors.d.ts +31 -1
  91. package/dist/lib/brewing/colors.js +34 -1
  92. package/dist/lib/brewing/marks/arcs.js +9 -4
  93. package/dist/lib/brewing/marks/boxes.js +8 -4
  94. package/dist/lib/brewing/marks/lines.js +13 -2
  95. package/dist/lib/brewing/marks/points.js +7 -2
  96. package/dist/lib/brewing/marks/swarm.js +6 -2
  97. package/dist/lib/brewing/marks/violins.js +8 -4
  98. package/dist/lib/preset.d.ts +11 -1
  99. package/dist/lib/preset.js +16 -4
  100. package/package.json +1 -1
  101. package/dist/Plot/Arc.svelte +0 -30
  102. package/dist/Plot/Arc.svelte.d.ts +0 -18
  103. package/dist/lib/brewer.d.ts +0 -9
  104. package/dist/lib/brewer.js +0 -25
  105. package/dist/lib/brewing/BoxBrewer.svelte.d.ts +0 -8
  106. package/dist/lib/brewing/BoxBrewer.svelte.js +0 -14
  107. package/dist/lib/brewing/CartesianBrewer.svelte.d.ts +0 -8
  108. package/dist/lib/brewing/CartesianBrewer.svelte.js +0 -21
  109. package/dist/lib/brewing/PieBrewer.svelte.d.ts +0 -8
  110. package/dist/lib/brewing/PieBrewer.svelte.js +0 -14
  111. package/dist/lib/brewing/QuartileBrewer.svelte.d.ts +0 -9
  112. package/dist/lib/brewing/QuartileBrewer.svelte.js +0 -51
  113. package/dist/lib/brewing/ViolinBrewer.svelte.d.ts +0 -8
  114. package/dist/lib/brewing/ViolinBrewer.svelte.js +0 -14
  115. package/dist/lib/brewing/axes.svelte.d.ts +0 -66
  116. package/dist/lib/brewing/axes.svelte.js +0 -270
  117. package/dist/lib/brewing/bars.svelte.d.ts +0 -56
  118. package/dist/lib/brewing/bars.svelte.js +0 -201
  119. package/dist/lib/brewing/brewer.svelte.d.ts +0 -124
  120. package/dist/lib/brewing/brewer.svelte.js +0 -277
  121. package/dist/lib/brewing/dimensions.svelte.d.ts +0 -35
  122. package/dist/lib/brewing/dimensions.svelte.js +0 -56
  123. package/dist/lib/brewing/index.svelte.d.ts +0 -118
  124. package/dist/lib/brewing/index.svelte.js +0 -205
  125. package/dist/lib/brewing/legends.svelte.d.ts +0 -48
  126. package/dist/lib/brewing/legends.svelte.js +0 -137
  127. package/dist/lib/brewing/marks/areas.d.ts +0 -31
  128. package/dist/lib/brewing/marks/areas.js +0 -72
  129. package/dist/lib/brewing/marks/bars.d.ts +0 -1
  130. package/dist/lib/brewing/marks/bars.js +0 -49
  131. package/dist/lib/brewing/scales.svelte.d.ts +0 -24
  132. package/dist/lib/brewing/scales.svelte.js +0 -82
  133. package/dist/lib/context.d.ts +0 -13
  134. package/dist/lib/context.js +0 -131
  135. package/dist/lib/plot/chartProps.d.ts +0 -177
  136. package/dist/lib/plot/chartProps.js +0 -76
  137. package/dist/lib/scales.svelte.d.ts +0 -35
  138. package/dist/lib/scales.svelte.js +0 -151
  139. package/dist/lib/ticks.d.ts +0 -36
  140. 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 { ChartBrewer } from './lib/brewing/brewer.svelte.js'
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
- const brewer = new ChartBrewer()
53
- setContext('chart-brewer', brewer)
54
-
55
- function buildChannels(): Channels {
56
- const channels: Channels = {}
57
- if (x) channels.x = x
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
- brewer.update({
71
- data: spec.data,
72
- channels: spec.channels,
73
- width,
74
- height,
75
- mode,
76
- layers: spec.layers
77
- })
78
- } else {
79
- brewer.update({ data, channels: buildChannels(), width, height, mode })
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
- <div class="chart-container" data-chart-root>
85
- <svg {width} {height} viewBox="0 0 {width} {height}" role="img" aria-label="Chart visualization">
86
- <g class="chart-area" data-chart-canvas>
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>
@@ -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,
@@ -11,6 +11,8 @@ type Props = {
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;
@@ -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 "./Arc.svelte";
9
+ export { default as Arc } from "../geoms/Arc.svelte";
@@ -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 './Arc.svelte'
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,
@@ -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
- point: number;
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[];
@@ -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((g) => g.options?.stack)
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
- const stackField = [colorField, patternField].find((f) => f && f !== xField) ?? colorField
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 = this.#yDomain ?? this.#resolveBoxDomain() ?? this.#resolveStackDomain(field)
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 ?? distinct(this.#data, field)
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>
@@ -4,6 +4,7 @@ type Props = {
4
4
  x?: string;
5
5
  y?: string;
6
6
  fill?: string;
7
+ alpha?: number;
7
8
  width?: number;
8
9
  height?: number;
9
10
  mode?: 'light' | 'dark';
@@ -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>
@@ -11,6 +11,7 @@ type Props = {
11
11
  color?: string;
12
12
  symbol?: string;
13
13
  size?: string;
14
+ alpha?: number;
14
15
  width?: number;
15
16
  height?: number;
16
17
  mode?: 'light' | 'dark';
@@ -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>
@@ -10,6 +10,7 @@ type Props = {
10
10
  y?: string;
11
11
  color?: string;
12
12
  stat?: string;
13
+ alpha?: number;
13
14
  symbol?: string;
14
15
  curve?: 'linear' | 'smooth' | 'step';
15
16
  label?: boolean | string | ((data: Row) => unknown);
@@ -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 @@ type Props = {
13
13
  mode?: 'light' | 'dark';
14
14
  legend?: boolean;
15
15
  stat?: string;
16
+ alpha?: number;
16
17
  };
17
18
  declare const PieChart: import("svelte").Component<Props, {}, "">;
18
19
  type PieChart = ReturnType<typeof PieChart>;
@@ -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>
@@ -11,6 +11,7 @@ type Props = {
11
11
  color?: string;
12
12
  symbol?: string;
13
13
  size?: string;
14
+ alpha?: number;
14
15
  label?: boolean | string | ((data: Row) => unknown);
15
16
  tooltip?: boolean | ((data: Row) => string);
16
17
  width?: number;
@@ -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>