@rokkit/chart 1.3.13 → 1.3.15
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 +4 -1
- package/dist/Plot.svelte +11 -0
- package/dist/Plot.svelte.d.ts +7 -0
- package/dist/PlotState.svelte.js +2 -0
- package/dist/Sparkline.svelte +200 -10
- package/dist/Sparkline.svelte.d.ts +11 -0
- package/dist/lib/plot/types.d.ts +1 -0
- package/dist/lib/plot/types.js +1 -0
- package/package.json +1 -1
package/dist/AnimatedPlot.svelte
CHANGED
|
@@ -202,7 +202,10 @@
|
|
|
202
202
|
})
|
|
203
203
|
|
|
204
204
|
onDestroy(() => {
|
|
205
|
-
|
|
205
|
+
// onDestroy is the one lifecycle hook that also runs during SSR, where
|
|
206
|
+
// cancelAnimationFrame is undefined — guard it so the component can be
|
|
207
|
+
// server-rendered / prerendered (rafId is only ever set in the browser).
|
|
208
|
+
if (typeof cancelAnimationFrame !== 'undefined') cancelAnimationFrame(rafId)
|
|
206
209
|
clearInterval(reducedInterval)
|
|
207
210
|
})
|
|
208
211
|
|
package/dist/Plot.svelte
CHANGED
|
@@ -58,6 +58,13 @@
|
|
|
58
58
|
onselect?: (detail: unknown) => void
|
|
59
59
|
selectable?: boolean
|
|
60
60
|
selected?: Row[]
|
|
61
|
+
/** Data-coordinate crossing point of the axes: `[xCross, yCross]`. Drives
|
|
62
|
+
* quadrant mode — where the origin sits relative to the domain makes a chart
|
|
63
|
+
* 1- / 2- / 4-quadrant. Omit a component to leave that axis auto (crosses at 0
|
|
64
|
+
* when the domain spans it, else edge-pinned). Also settable via `spec.axisOrigin`. */
|
|
65
|
+
axisOrigin?: [number | undefined, number | undefined]
|
|
66
|
+
/** Nudge an edge-pinned axis outward by N px (Q1 only). Also via `spec.axisOffset`. */
|
|
67
|
+
axisOffset?: number
|
|
61
68
|
/** Animate marks on data/flip changes (opt-out for e.g. AnimatedPlot, which
|
|
62
69
|
* tweens its own frames). Enabled one frame after the width settles so the
|
|
63
70
|
* initial layout paints un-animated. Default `true`. */
|
|
@@ -94,6 +101,8 @@
|
|
|
94
101
|
onselect = undefined,
|
|
95
102
|
selectable = false,
|
|
96
103
|
selected = $bindable([]),
|
|
104
|
+
axisOrigin = undefined,
|
|
105
|
+
axisOffset = undefined,
|
|
97
106
|
animate = true,
|
|
98
107
|
children
|
|
99
108
|
}: Props = $props()
|
|
@@ -142,6 +151,8 @@
|
|
|
142
151
|
colorScheme: spec?.colorScheme,
|
|
143
152
|
colorMidpoint: spec?.colorMidpoint,
|
|
144
153
|
orientation: orientation ?? spec?.orientation,
|
|
154
|
+
axisOrigin: spec?.axisOrigin ?? axisOrigin,
|
|
155
|
+
axisOffset: spec?.axisOffset ?? axisOffset,
|
|
145
156
|
sort: spec?.sort,
|
|
146
157
|
continuousCategory: spec?.continuousCategory,
|
|
147
158
|
chartPreset,
|
package/dist/Plot.svelte.d.ts
CHANGED
|
@@ -41,6 +41,13 @@ type Props = {
|
|
|
41
41
|
onselect?: (detail: unknown) => void;
|
|
42
42
|
selectable?: boolean;
|
|
43
43
|
selected?: Row[];
|
|
44
|
+
/** Data-coordinate crossing point of the axes: `[xCross, yCross]`. Drives
|
|
45
|
+
* quadrant mode — where the origin sits relative to the domain makes a chart
|
|
46
|
+
* 1- / 2- / 4-quadrant. Omit a component to leave that axis auto (crosses at 0
|
|
47
|
+
* when the domain spans it, else edge-pinned). Also settable via `spec.axisOrigin`. */
|
|
48
|
+
axisOrigin?: [number | undefined, number | undefined];
|
|
49
|
+
/** Nudge an edge-pinned axis outward by N px (Q1 only). Also via `spec.axisOffset`. */
|
|
50
|
+
axisOffset?: number;
|
|
44
51
|
/** Animate marks on data/flip changes (opt-out for e.g. AnimatedPlot, which
|
|
45
52
|
* tweens its own frames). Enabled one frame after the width settles so the
|
|
46
53
|
* initial layout paints un-animated. Default `true`. */
|
package/dist/PlotState.svelte.js
CHANGED
|
@@ -425,6 +425,7 @@ export class PlotState {
|
|
|
425
425
|
this.#selectable = config.selectable ?? false
|
|
426
426
|
if (config.selected) this.#selected = new SvelteSet(config.selected)
|
|
427
427
|
this.#axisOffset = config.axisOffset ?? 0
|
|
428
|
+
this.axisOrigin = config.axisOrigin ?? [undefined, undefined]
|
|
428
429
|
this.#marginOverride = config.margin ?? undefined
|
|
429
430
|
this.#orientationOverride = config.orientation ?? undefined
|
|
430
431
|
this.#continuousCategory = config.continuousCategory ?? false
|
|
@@ -453,6 +454,7 @@ export class PlotState {
|
|
|
453
454
|
if (config.onselect !== undefined) this.#onselect = config.onselect
|
|
454
455
|
if (config.selectable !== undefined) this.#selectable = config.selectable
|
|
455
456
|
if (config.axisOffset !== undefined) this.#axisOffset = config.axisOffset
|
|
457
|
+
this.axisOrigin = config.axisOrigin ?? [undefined, undefined]
|
|
456
458
|
this.#marginOverride = config.margin ?? undefined
|
|
457
459
|
this.#orientationOverride = config.orientation ?? undefined
|
|
458
460
|
this.#continuousCategory = config.continuousCategory ?? false
|
package/dist/Sparkline.svelte
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
import { line as d3line, area as d3area, curveCatmullRom } from 'd3-shape'
|
|
4
4
|
import PatternDef from './patterns/PatternDef.svelte'
|
|
5
5
|
import { PATTERNS } from './patterns/patterns.js'
|
|
6
|
+
import { resolveHighlight } from './lib/highlight.js'
|
|
7
|
+
import { computeTrend } from './lib/trend.js'
|
|
8
|
+
|
|
9
|
+
type HighlightSelector =
|
|
10
|
+
| 'first'
|
|
11
|
+
| 'last'
|
|
12
|
+
| 'min'
|
|
13
|
+
| 'max'
|
|
14
|
+
| number
|
|
15
|
+
| ((row: { x: number; y: number }, i: number) => boolean)
|
|
16
|
+
|
|
17
|
+
type TrendMethod = string | number | { type: string; [k: string]: unknown }
|
|
6
18
|
|
|
7
19
|
type Props = {
|
|
8
20
|
data?: number[] | Record<string, unknown>[]
|
|
@@ -15,6 +27,9 @@
|
|
|
15
27
|
height?: number
|
|
16
28
|
min?: number
|
|
17
29
|
max?: number
|
|
30
|
+
baseline?: number
|
|
31
|
+
highlight?: HighlightSelector | HighlightSelector[]
|
|
32
|
+
trend?: TrendMethod | TrendMethod[]
|
|
18
33
|
}
|
|
19
34
|
|
|
20
35
|
let {
|
|
@@ -27,7 +42,10 @@
|
|
|
27
42
|
width = 80,
|
|
28
43
|
height = 24,
|
|
29
44
|
min = undefined,
|
|
30
|
-
max = undefined
|
|
45
|
+
max = undefined,
|
|
46
|
+
baseline = undefined,
|
|
47
|
+
highlight = undefined,
|
|
48
|
+
trend = undefined
|
|
31
49
|
}: Props = $props()
|
|
32
50
|
|
|
33
51
|
const values = $derived(
|
|
@@ -36,8 +54,24 @@
|
|
|
36
54
|
)
|
|
37
55
|
)
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
const
|
|
57
|
+
// Adapter to the pure geom utilities (they operate on {x,y} rows).
|
|
58
|
+
const rows = $derived(values.map((v, i) => ({ x: i, y: v })))
|
|
59
|
+
|
|
60
|
+
const hasNegative = $derived(values.some((v) => v < 0))
|
|
61
|
+
// Bars with negative values are meaningless when measured from the pixel bottom, so a
|
|
62
|
+
// bar sparkline auto-anchors at 0 when any value is negative. Everything else is opt-in.
|
|
63
|
+
const effectiveBaseline = $derived(baseline ?? (type === 'bar' && hasNegative ? 0 : undefined))
|
|
64
|
+
|
|
65
|
+
const rawMin = $derived(Math.min(...values))
|
|
66
|
+
const rawMax = $derived(Math.max(...values))
|
|
67
|
+
// Explicit min/max win; otherwise extend the auto domain to include the baseline so it
|
|
68
|
+
// (and the full negative extent) stay on-canvas.
|
|
69
|
+
const yMin = $derived(
|
|
70
|
+
min ?? (effectiveBaseline !== undefined ? Math.min(rawMin, effectiveBaseline) : rawMin)
|
|
71
|
+
)
|
|
72
|
+
const yMax = $derived(
|
|
73
|
+
max ?? (effectiveBaseline !== undefined ? Math.max(rawMax, effectiveBaseline) : rawMax)
|
|
74
|
+
)
|
|
41
75
|
|
|
42
76
|
const xScale = $derived(
|
|
43
77
|
scaleLinear()
|
|
@@ -46,6 +80,60 @@
|
|
|
46
80
|
)
|
|
47
81
|
const yScale = $derived(scaleLinear().domain([yMin, yMax]).range([height, 0]))
|
|
48
82
|
|
|
83
|
+
// When no baseline is in effect, anchor at the pixel bottom — preserves the classic
|
|
84
|
+
// min-anchored sparkbar look (Math.min/abs below both collapse to the old formula).
|
|
85
|
+
const barAnchorY = $derived(effectiveBaseline !== undefined ? yScale(effectiveBaseline) : height)
|
|
86
|
+
|
|
87
|
+
const highlightSelectors = $derived(
|
|
88
|
+
Array.isArray(highlight)
|
|
89
|
+
? highlight
|
|
90
|
+
: highlight === null || highlight === undefined
|
|
91
|
+
? []
|
|
92
|
+
: [highlight]
|
|
93
|
+
)
|
|
94
|
+
const highlightIndices = $derived.by(() => {
|
|
95
|
+
const seen = new Set<number>()
|
|
96
|
+
for (const sel of highlightSelectors) {
|
|
97
|
+
for (const i of resolveHighlight(rows, sel, { y: 'y' })) seen.add(i)
|
|
98
|
+
}
|
|
99
|
+
return [...seen]
|
|
100
|
+
})
|
|
101
|
+
const highlightMarks = $derived(
|
|
102
|
+
highlightIndices
|
|
103
|
+
.map((i) => ({ i, cx: xScale(i), cy: yScale(values[i]) }))
|
|
104
|
+
.filter((m) => Number.isFinite(m.cx) && Number.isFinite(m.cy))
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const trendMethods = $derived(
|
|
108
|
+
Array.isArray(trend) ? trend : trend === null || trend === undefined ? [] : [trend]
|
|
109
|
+
)
|
|
110
|
+
const typeOf = (m: TrendMethod) => {
|
|
111
|
+
const t = typeof m === 'string' ? m : typeof m === 'number' ? 'value' : (m?.type ?? '')
|
|
112
|
+
return t === 'mean' ? 'avg' : t
|
|
113
|
+
}
|
|
114
|
+
const trendPaths = $derived.by(() => {
|
|
115
|
+
const out: { d: string; type: string; i: number }[] = []
|
|
116
|
+
trendMethods.forEach((m, idx) => {
|
|
117
|
+
const res = computeTrend(rows, { x: 'x', y: 'y' }, m)
|
|
118
|
+
if (!res) return
|
|
119
|
+
if (res.kind === 'constant') {
|
|
120
|
+
const yy = yScale(res.value)
|
|
121
|
+
if (Number.isFinite(yy))
|
|
122
|
+
out.push({ d: `M0,${yy} L${width},${yy}`, type: typeOf(m), i: idx })
|
|
123
|
+
} else {
|
|
124
|
+
const pts = res.values
|
|
125
|
+
.map((v, i) => ({ vx: xScale(i), vy: yScale(v) }))
|
|
126
|
+
.filter((p) => Number.isFinite(p.vx) && Number.isFinite(p.vy))
|
|
127
|
+
const gen = d3line<{ vx: number; vy: number }>()
|
|
128
|
+
.x((p) => p.vx)
|
|
129
|
+
.y((p) => p.vy)
|
|
130
|
+
const d = gen(pts)
|
|
131
|
+
if (d) out.push({ d, type: typeOf(m), i: idx })
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
return out
|
|
135
|
+
})
|
|
136
|
+
|
|
49
137
|
const linePath = $derived.by(() => {
|
|
50
138
|
const gen = d3line<number>()
|
|
51
139
|
.x((_, i) => xScale(i))
|
|
@@ -54,15 +142,40 @@
|
|
|
54
142
|
return gen(values)
|
|
55
143
|
})
|
|
56
144
|
|
|
145
|
+
// Area fill anchors at the baseline when one is in effect (so a mixed-sign
|
|
146
|
+
// area fills up above / down below the crossing), else at the pixel bottom.
|
|
147
|
+
const baselineY = $derived(effectiveBaseline !== undefined ? yScale(effectiveBaseline) : null)
|
|
148
|
+
|
|
57
149
|
const areaPath = $derived.by(() => {
|
|
58
150
|
const gen = d3area<number>()
|
|
59
151
|
.x((_, i) => xScale(i))
|
|
60
|
-
.y0(height)
|
|
152
|
+
.y0(baselineY ?? height)
|
|
61
153
|
.y1((v) => yScale(v))
|
|
62
154
|
if (curve === 'smooth') gen.curve(curveCatmullRom)
|
|
63
155
|
return gen(values)
|
|
64
156
|
})
|
|
65
157
|
|
|
158
|
+
// When a baseline is in effect, split the fill into above/below regions (each
|
|
159
|
+
// clamped at the baseline) so themes can colour positive vs negative fills.
|
|
160
|
+
const areaAbovePath = $derived.by(() => {
|
|
161
|
+
if (baselineY === null) return null
|
|
162
|
+
const gen = d3area<number>()
|
|
163
|
+
.x((_, i) => xScale(i))
|
|
164
|
+
.y0(baselineY)
|
|
165
|
+
.y1((v) => Math.min(yScale(v), baselineY))
|
|
166
|
+
if (curve === 'smooth') gen.curve(curveCatmullRom)
|
|
167
|
+
return gen(values)
|
|
168
|
+
})
|
|
169
|
+
const areaBelowPath = $derived.by(() => {
|
|
170
|
+
if (baselineY === null) return null
|
|
171
|
+
const gen = d3area<number>()
|
|
172
|
+
.x((_, i) => xScale(i))
|
|
173
|
+
.y0(baselineY)
|
|
174
|
+
.y1((v) => Math.max(yScale(v), baselineY))
|
|
175
|
+
if (curve === 'smooth') gen.curve(curveCatmullRom)
|
|
176
|
+
return gen(values)
|
|
177
|
+
})
|
|
178
|
+
|
|
66
179
|
const barWidth = $derived(Math.max(1, width / values.length - 1))
|
|
67
180
|
|
|
68
181
|
const strokeColor = $derived(`rgb(var(--color-${color}-500, 100,116,139))`)
|
|
@@ -72,7 +185,7 @@
|
|
|
72
185
|
const patternMarks = $derived(pattern ? (PATTERNS[pattern] ?? null) : null)
|
|
73
186
|
</script>
|
|
74
187
|
|
|
75
|
-
<svg {width} {height} style="overflow: visible; display: block;">
|
|
188
|
+
<svg {width} {height} style="overflow: visible; display: block; --spark-area-fill: {fillColor};">
|
|
76
189
|
{#if patternMarks}
|
|
77
190
|
<defs>
|
|
78
191
|
<PatternDef id={patternId} marks={patternMarks} stroke={strokeColor} />
|
|
@@ -89,7 +202,22 @@
|
|
|
89
202
|
stroke-linecap="round"
|
|
90
203
|
/>
|
|
91
204
|
{:else if type === 'area'}
|
|
92
|
-
|
|
205
|
+
{#if baselineY !== null}
|
|
206
|
+
<path
|
|
207
|
+
d={areaAbovePath}
|
|
208
|
+
data-plot-area
|
|
209
|
+
data-plot-area-sign="above"
|
|
210
|
+
fill={patternMarks ? `url(#${patternId})` : undefined}
|
|
211
|
+
/>
|
|
212
|
+
<path
|
|
213
|
+
d={areaBelowPath}
|
|
214
|
+
data-plot-area
|
|
215
|
+
data-plot-area-sign="below"
|
|
216
|
+
fill={patternMarks ? `url(#${patternId})` : undefined}
|
|
217
|
+
/>
|
|
218
|
+
{:else}
|
|
219
|
+
<path d={areaPath} data-plot-area fill={patternMarks ? `url(#${patternId})` : undefined} />
|
|
220
|
+
{/if}
|
|
93
221
|
<path
|
|
94
222
|
d={linePath}
|
|
95
223
|
fill="none"
|
|
@@ -100,23 +228,85 @@
|
|
|
100
228
|
/>
|
|
101
229
|
{:else if type === 'bar'}
|
|
102
230
|
{#each values as v, i (i)}
|
|
231
|
+
{@const vy = yScale(v)}
|
|
232
|
+
{@const top = Math.min(vy, barAnchorY)}
|
|
233
|
+
{@const barHeight = Math.abs(vy - barAnchorY)}
|
|
103
234
|
<rect
|
|
104
235
|
x={xScale(i) - barWidth / 2}
|
|
105
|
-
y={
|
|
236
|
+
y={top}
|
|
106
237
|
width={barWidth}
|
|
107
|
-
height={
|
|
238
|
+
height={barHeight}
|
|
108
239
|
fill={strokeColor}
|
|
109
240
|
/>
|
|
110
241
|
{#if patternMarks}
|
|
111
242
|
<rect
|
|
112
243
|
x={xScale(i) - barWidth / 2}
|
|
113
|
-
y={
|
|
244
|
+
y={top}
|
|
114
245
|
width={barWidth}
|
|
115
|
-
height={
|
|
246
|
+
height={barHeight}
|
|
116
247
|
fill="url(#{patternId})"
|
|
117
248
|
pointer-events="none"
|
|
118
249
|
/>
|
|
119
250
|
{/if}
|
|
120
251
|
{/each}
|
|
121
252
|
{/if}
|
|
253
|
+
|
|
254
|
+
{#if trendPaths.length}
|
|
255
|
+
<g data-plot-geom="trend">
|
|
256
|
+
{#each trendPaths as p (p.i)}
|
|
257
|
+
<path d={p.d} data-plot-trend={p.type} />
|
|
258
|
+
{/each}
|
|
259
|
+
</g>
|
|
260
|
+
{/if}
|
|
261
|
+
|
|
262
|
+
{#if effectiveBaseline !== undefined}
|
|
263
|
+
<line x1={0} y1={barAnchorY} x2={width} y2={barAnchorY} data-plot-baseline />
|
|
264
|
+
{/if}
|
|
265
|
+
|
|
266
|
+
{#if highlightMarks.length}
|
|
267
|
+
<g data-plot-geom="highlight">
|
|
268
|
+
{#each highlightMarks as m (m.i)}
|
|
269
|
+
<circle cx={m.cx} cy={m.cy} data-plot-highlight />
|
|
270
|
+
{/each}
|
|
271
|
+
</g>
|
|
272
|
+
{/if}
|
|
122
273
|
</svg>
|
|
274
|
+
|
|
275
|
+
<style>
|
|
276
|
+
[data-plot-area] {
|
|
277
|
+
fill: var(--spark-area-fill, rgba(var(--color-primary-300), 0.25));
|
|
278
|
+
stroke: none;
|
|
279
|
+
}
|
|
280
|
+
/* Positive vs negative regions of a baseline-anchored area — default to the
|
|
281
|
+
same fill; a theme can distinguish them via these vars. */
|
|
282
|
+
[data-plot-area][data-plot-area-sign='above'] {
|
|
283
|
+
fill: var(--chart-area-above-color, var(--spark-area-fill));
|
|
284
|
+
}
|
|
285
|
+
[data-plot-area][data-plot-area-sign='below'] {
|
|
286
|
+
fill: var(--chart-area-below-color, var(--spark-area-fill));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
[data-plot-baseline] {
|
|
290
|
+
stroke: var(--chart-baseline-color, currentColor);
|
|
291
|
+
stroke-width: var(--chart-baseline-width, 1);
|
|
292
|
+
stroke-dasharray: var(--chart-baseline-dash, 4 4);
|
|
293
|
+
opacity: var(--chart-baseline-opacity, 0.5);
|
|
294
|
+
pointer-events: none;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
[data-plot-highlight] {
|
|
298
|
+
fill: var(--chart-highlight-color, rgb(var(--color-accent-500, 194 65 12)));
|
|
299
|
+
stroke: var(--chart-highlight-ring, none);
|
|
300
|
+
r: var(--chart-highlight-radius, 3);
|
|
301
|
+
pointer-events: none;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
[data-plot-trend] {
|
|
305
|
+
fill: none;
|
|
306
|
+
stroke: var(--chart-trend-color, currentColor);
|
|
307
|
+
stroke-width: var(--chart-trend-width, 1);
|
|
308
|
+
stroke-dasharray: var(--chart-trend-dash, 4 4);
|
|
309
|
+
opacity: var(--chart-trend-opacity, 0.7);
|
|
310
|
+
pointer-events: none;
|
|
311
|
+
}
|
|
312
|
+
</style>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { PATTERNS } from './patterns/patterns.js';
|
|
2
|
+
type HighlightSelector = 'first' | 'last' | 'min' | 'max' | number | ((row: {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}, i: number) => boolean);
|
|
6
|
+
type TrendMethod = string | number | {
|
|
7
|
+
type: string;
|
|
8
|
+
[k: string]: unknown;
|
|
9
|
+
};
|
|
2
10
|
type Props = {
|
|
3
11
|
data?: number[] | Record<string, unknown>[];
|
|
4
12
|
field?: string;
|
|
@@ -10,6 +18,9 @@ type Props = {
|
|
|
10
18
|
height?: number;
|
|
11
19
|
min?: number;
|
|
12
20
|
max?: number;
|
|
21
|
+
baseline?: number;
|
|
22
|
+
highlight?: HighlightSelector | HighlightSelector[];
|
|
23
|
+
trend?: TrendMethod | TrendMethod[];
|
|
13
24
|
};
|
|
14
25
|
declare const Sparkline: import("svelte").Component<Props, {}, "">;
|
|
15
26
|
type Sparkline = ReturnType<typeof Sparkline>;
|
package/dist/lib/plot/types.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export type PlotSpec = {
|
|
|
33
33
|
xLabel?: string | undefined;
|
|
34
34
|
yLabel?: string | undefined;
|
|
35
35
|
axisOrigin?: [number, number] | undefined;
|
|
36
|
+
axisOffset?: number | undefined;
|
|
36
37
|
colorScale?: "categorical" | "sequential" | "diverging" | undefined;
|
|
37
38
|
colorScheme?: string | undefined;
|
|
38
39
|
colorMidpoint?: number | undefined;
|
package/dist/lib/plot/types.js
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
* @property {string} [xLabel]
|
|
34
34
|
* @property {string} [yLabel]
|
|
35
35
|
* @property {[number, number]} [axisOrigin]
|
|
36
|
+
* @property {number} [axisOffset]
|
|
36
37
|
* @property {'categorical'|'sequential'|'diverging'} [colorScale]
|
|
37
38
|
* @property {string} [colorScheme]
|
|
38
39
|
* @property {number} [colorMidpoint]
|