Skip to content

Commit c7fe07b

Browse files
authored
refactor(chart): clarify x-axis helpers
1 parent 185b752 commit c7fe07b

3 files changed

Lines changed: 62 additions & 16 deletions

File tree

‎examples/official-site/sqlpage/migrations/01_documentation.sql‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
669669
('xtitle', 'Title of the x axis, displayed below it.', 'TEXT', TRUE, TRUE),
670670
('ytitle', 'Title of the y axis, displayed to its left.', 'TEXT', TRUE, TRUE),
671671
('ztitle', 'Title of the z axis, displayed in tooltips.', 'TEXT', TRUE, TRUE),
672-
('xticks', 'Number of tick positions on a numeric x-axis. On category and time axes, this is a target for label density, so the visible label count may differ.', 'INTEGER', TRUE, TRUE),
672+
('xticks', 'Number of tick positions on a numeric x-axis. For example, 5 requests five evenly spaced positions, including the two ends. On category and time axes, it asks ApexCharts to show up to that many labels; it may show fewer to keep labels from overlapping.', 'INTEGER', TRUE, TRUE),
673673
('yticks', 'Number of ticks on the y axis.', 'INTEGER', TRUE, TRUE),
674674
('ystep', 'Step between ticks on the y axis.', 'REAL', TRUE, TRUE),
675675
('marker', 'Marker size', 'REAL', TRUE, TRUE),

‎sqlpage/apexcharts.js‎

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,17 @@ sqlpage_chart = (() => {
6161
/** @param {ChartSeries[]} series */
6262
const x_is_text = (series) => typeof series[0]?.data?.[0]?.x === "string";
6363

64-
/** @param {ChartSeries[]} series @param {string} chart_type */
65-
function xaxis_type_for(series, chart_type, is_timeseries, is_horizontal) {
64+
/**
65+
* Numeric x values need an explicit axis type to retain their proportional
66+
* spacing; otherwise ApexCharts treats them as evenly spaced categories.
67+
*
68+
* @param {ChartSeries[]} series
69+
* @param {{chart_type:string, is_timeseries:boolean, is_horizontal:boolean}} options
70+
*/
71+
function xaxis_type_for(
72+
series,
73+
{ chart_type, is_timeseries, is_horizontal },
74+
) {
6675
if (is_timeseries) return "datetime";
6776
if (x_is_text(series)) return "category";
6877
if (
@@ -73,6 +82,18 @@ sqlpage_chart = (() => {
7382
return "numeric";
7483
}
7584

85+
/**
86+
* ApexCharts expects intervals for numeric axes, while SQLPage exposes the
87+
* more intuitive number of tick positions to users.
88+
*
89+
* @param {number|undefined} xticks
90+
* @param {string|undefined} xaxis_type
91+
*/
92+
function xaxis_tick_amount(xticks, xaxis_type) {
93+
if (!xticks) return;
94+
return xaxis_type === "numeric" ? Math.max(1, xticks - 1) : xticks;
95+
}
96+
7697
/**
7798
* @param {ChartSeries[]} series
7899
* @returns {XValue[]} every x the series hold, in their own order where they
@@ -225,12 +246,11 @@ sqlpage_chart = (() => {
225246
let colors = palette;
226247

227248
let series = Object.values(series_map);
228-
const xaxis_type = xaxis_type_for(
229-
series,
249+
const xaxis_type = xaxis_type_for(series, {
230250
chart_type,
231251
is_timeseries,
232-
!!data.horizontal,
233-
);
252+
is_horizontal: !!data.horizontal,
253+
});
234254

235255
let labels;
236256
if (chart_type === "pie") {
@@ -386,10 +406,7 @@ sqlpage_chart = (() => {
386406
series,
387407
};
388408
if (labels) options.labels = labels;
389-
// ApexCharts counts numeric intervals rather than tick positions.
390-
if (data.xticks)
391-
options.xaxis.tickAmount =
392-
xaxis_type === "numeric" ? Math.max(1, data.xticks - 1) : data.xticks;
409+
options.xaxis.tickAmount = xaxis_tick_amount(data.xticks, xaxis_type);
393410
const chart = new ApexCharts(chartContainer, options);
394411
chart.render();
395412
if (window.charts) window.charts.push(chart);

‎tests/js/chart_series.spec.ts‎

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,31 @@ test("uses a continuous axis for numeric Cartesian x values", () => {
3737
const numeric = [series("a", { x: 1, y: 1 }, { x: 12, y: 12 })];
3838

3939
for (const type of ["line", "area", "bar", "scatter", "bubble"])
40-
assert.equal(xaxis_type_for(numeric, type, false, false), "numeric");
40+
assert.equal(
41+
xaxis_type_for(numeric, {
42+
chart_type: type,
43+
is_timeseries: false,
44+
is_horizontal: false,
45+
}),
46+
"numeric",
47+
);
4148
});
4249

4350
test("keeps text and time x values on their respective axes", () => {
4451
assert.equal(
45-
xaxis_type_for([series("a", { x: "Q1", y: 1 })], "bar", false, false),
52+
xaxis_type_for([series("a", { x: "Q1", y: 1 })], {
53+
chart_type: "bar",
54+
is_timeseries: false,
55+
is_horizontal: false,
56+
}),
4657
"category",
4758
);
4859
assert.equal(
49-
xaxis_type_for([series("a", { x: 1, y: 1 })], "bar", true, false),
60+
xaxis_type_for([series("a", { x: 1, y: 1 })], {
61+
chart_type: "bar",
62+
is_timeseries: true,
63+
is_horizontal: false,
64+
}),
5065
"datetime",
5166
);
5267
});
@@ -55,8 +70,22 @@ test("does not turn category-oriented charts into numeric axes", () => {
5570
const numeric = [series("a", { x: 1, y: 1 })];
5671

5772
for (const type of ["heatmap", "rangeBar", "pie", "treemap"])
58-
assert.equal(xaxis_type_for(numeric, type, false, false), undefined);
59-
assert.equal(xaxis_type_for(numeric, "bar", false, true), undefined);
73+
assert.equal(
74+
xaxis_type_for(numeric, {
75+
chart_type: type,
76+
is_timeseries: false,
77+
is_horizontal: false,
78+
}),
79+
undefined,
80+
);
81+
assert.equal(
82+
xaxis_type_for(numeric, {
83+
chart_type: "bar",
84+
is_timeseries: false,
85+
is_horizontal: true,
86+
}),
87+
undefined,
88+
);
6089
});
6190

6291
test("merged_x_values keeps the order the series agree on", () => {

0 commit comments

Comments
 (0)