@pushwoosh/kit-charts 0.0.10 → 0.0.12
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/ai-documentation.md +6 -0
- package/core/Chart/Axes.js +4 -2
- package/core/model/build-model.js +6 -1
- package/core/scale/linear.d.ts +2 -0
- package/core/scale/linear.js +18 -4
- package/core/types/options.d.ts +0 -3
- package/package.json +1 -1
package/ai-documentation.md
CHANGED
|
@@ -92,6 +92,12 @@ own `formatter` or `format` wins over it.
|
|
|
92
92
|
the step is chosen from the candidates that stay integral at its magnitude, and
|
|
93
93
|
never falls below 1.
|
|
94
94
|
|
|
95
|
+
`tickAmount` is Highcharts' demand and not a hint: the y axis stretches the end
|
|
96
|
+
the caller left open until exactly that many ticks fit, so a count of 2 on a
|
|
97
|
+
`tickAmount: 5` axis still draws 0..4 and reads against a stable grid rather than
|
|
98
|
+
filling the plot. An end pinned with `max` cannot be stretched, so a tick amount
|
|
99
|
+
alongside one is ignored.
|
|
100
|
+
|
|
95
101
|
`labels.allowOverlap` defaults to false on both axes and on data labels. A label
|
|
96
102
|
whose box would run into one already placed loses its text — Highcharts hides
|
|
97
103
|
the label and keeps the tick, and so do we.
|
package/core/Chart/Axes.js
CHANGED
|
@@ -14,6 +14,8 @@ const ANCHOR = {
|
|
|
14
14
|
center: 'middle',
|
|
15
15
|
right: 'end'
|
|
16
16
|
};
|
|
17
|
+
/** `style.textAlign` wins over the anchor the axis derives from its own geometry. */
|
|
18
|
+
const anchorFor = (style, fallback) => style?.textAlign && ANCHOR[style.textAlign] || fallback;
|
|
17
19
|
/** What a tick draws: its own node if a formatter made one, its text otherwise. */
|
|
18
20
|
const tickContent = tick => {
|
|
19
21
|
if (tick.node !== undefined && tick.node !== null) {
|
|
@@ -33,7 +35,7 @@ function TickLabel({
|
|
|
33
35
|
const text = _jsx("text", {
|
|
34
36
|
x: x,
|
|
35
37
|
y: y,
|
|
36
|
-
textAnchor: anchor,
|
|
38
|
+
textAnchor: anchorFor(style, anchor),
|
|
37
39
|
...textProps(style),
|
|
38
40
|
children: children
|
|
39
41
|
});
|
|
@@ -89,7 +91,7 @@ function AxisTitle({
|
|
|
89
91
|
return _jsx("text", {
|
|
90
92
|
x: at.x,
|
|
91
93
|
y: at.y,
|
|
92
|
-
textAnchor: rotation === 0 ? anchor : 'middle',
|
|
94
|
+
textAnchor: rotation === 0 ? anchorFor(title.style, anchor) : 'middle',
|
|
93
95
|
transform: rotation === 0 ? undefined : `rotate(${rotation} ${at.x} ${at.y})`,
|
|
94
96
|
...textProps(title.style),
|
|
95
97
|
children: title.text
|
|
@@ -139,6 +139,7 @@ function buildYScale(axis, extent, range, hint, linked) {
|
|
|
139
139
|
max: axis.max === undefined
|
|
140
140
|
},
|
|
141
141
|
tickHint: hint,
|
|
142
|
+
tickCount: axis.tickAmount,
|
|
142
143
|
allowDecimals: axis.allowDecimals
|
|
143
144
|
});
|
|
144
145
|
}
|
|
@@ -337,7 +338,9 @@ export function buildChartModel({
|
|
|
337
338
|
}) => {
|
|
338
339
|
points.forEach(point => {
|
|
339
340
|
if (typeof point.x === 'string') {
|
|
340
|
-
point
|
|
341
|
+
// Highcharts reads a string in `[name, value]` as the point's name and
|
|
342
|
+
// places it by index; we key by category, and fall back where it misses.
|
|
343
|
+
point.band = !explicitCategories || categories.includes(point.x) ? point.x : categories[point.index] ?? point.x;
|
|
341
344
|
return;
|
|
342
345
|
}
|
|
343
346
|
if (!explicitCategories) {
|
|
@@ -347,6 +350,8 @@ export function buildChartModel({
|
|
|
347
350
|
point.band = categories[Number(point.x)] ?? categories[point.index] ?? String(point.x);
|
|
348
351
|
});
|
|
349
352
|
});
|
|
353
|
+
// A band still outside the list extends the axis: a surplus point is data, and
|
|
354
|
+
// dropping it would lose it without a word.
|
|
350
355
|
resolved.forEach(({
|
|
351
356
|
points
|
|
352
357
|
}) => {
|
package/core/scale/linear.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface LinearScaleOptions {
|
|
|
9
9
|
range: readonly [number, number];
|
|
10
10
|
nice?: boolean | NiceEnds;
|
|
11
11
|
tickHint?: number;
|
|
12
|
+
/** Highcharts' `tickAmount`: stretch the open end so exactly this many ticks fit. */
|
|
13
|
+
tickCount?: number;
|
|
12
14
|
/** False keeps every tick a whole number, as a count axis needs. */
|
|
13
15
|
allowDecimals?: boolean;
|
|
14
16
|
}
|
package/core/scale/linear.js
CHANGED
|
@@ -31,18 +31,32 @@ export function createLinearScale(options) {
|
|
|
31
31
|
range,
|
|
32
32
|
nice = false,
|
|
33
33
|
tickHint = 5,
|
|
34
|
+
tickCount,
|
|
34
35
|
allowDecimals = true
|
|
35
36
|
} = options;
|
|
36
37
|
let [min, max] = options.domain;
|
|
38
|
+
const niceMin = nice === true || typeof nice === 'object' && nice.min === true;
|
|
39
|
+
const niceMax = nice === true || typeof nice === 'object' && nice.max === true;
|
|
37
40
|
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
38
41
|
[min, max] = [0, 1];
|
|
39
42
|
} else if (min === max) {
|
|
40
43
|
const pad = Math.abs(min) || 1;
|
|
41
|
-
|
|
44
|
+
// An end the caller pinned stays put: padding both would take a `min: 0`
|
|
45
|
+
// count axis below zero on a day where every value is zero.
|
|
46
|
+
[min, max] = [min - (niceMin || !niceMax ? pad : 0), max + (niceMax || !niceMin ? pad : 0)];
|
|
42
47
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
if (tickCount !== undefined && tickCount > 1 && niceMax) {
|
|
49
|
+
let step = niceStep((max - min) / (tickCount - 1), allowDecimals);
|
|
50
|
+
if (niceMin) {
|
|
51
|
+
min = Math.floor(min / step) * step;
|
|
52
|
+
}
|
|
53
|
+
// Rounding the low end down lengthens the run, which can leave the last tick
|
|
54
|
+
// short of the data; widen the step until the fixed number of them covers it.
|
|
55
|
+
while (min + (tickCount - 1) * step < max) {
|
|
56
|
+
step = niceStep(step * 1.5, allowDecimals);
|
|
57
|
+
}
|
|
58
|
+
max = min + (tickCount - 1) * step;
|
|
59
|
+
} else if (niceMin || niceMax) {
|
|
46
60
|
const step = niceStep((max - min) / tickHint, allowDecimals);
|
|
47
61
|
if (niceMin) {
|
|
48
62
|
min = Math.floor(min / step) * step;
|
package/core/types/options.d.ts
CHANGED
|
@@ -86,10 +86,8 @@ export interface AxisLabelsOptions {
|
|
|
86
86
|
hint?: (ctx: AxisLabelContext) => string | undefined;
|
|
87
87
|
allowOverlap?: boolean;
|
|
88
88
|
align?: 'left' | 'center' | 'right';
|
|
89
|
-
rotation?: number;
|
|
90
89
|
x?: number;
|
|
91
90
|
y?: number;
|
|
92
|
-
padding?: number;
|
|
93
91
|
style?: TextStyle;
|
|
94
92
|
}
|
|
95
93
|
/** `zIndex` at or above this draws over the series instead of under it. */
|
|
@@ -168,7 +166,6 @@ export interface LegendOptions<TSeriesMeta = unknown> {
|
|
|
168
166
|
align?: 'left' | 'center' | 'right';
|
|
169
167
|
verticalAlign?: 'top' | 'middle' | 'bottom';
|
|
170
168
|
layout?: 'horizontal' | 'vertical';
|
|
171
|
-
margin?: number;
|
|
172
169
|
x?: number;
|
|
173
170
|
y?: number;
|
|
174
171
|
itemStyle?: TextStyle;
|