@pushwoosh/kit-charts 0.0.17 → 0.0.19
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.
|
@@ -81,6 +81,9 @@ const emptyExtent = () => ({
|
|
|
81
81
|
min: Infinity,
|
|
82
82
|
max: -Infinity
|
|
83
83
|
});
|
|
84
|
+
// Below four intervals the nice step jumps a whole magnitude and a count axis
|
|
85
|
+
// degenerates to two labels; a short card asks for fewer than that.
|
|
86
|
+
const MIN_Y_TICK_HINT = 4;
|
|
84
87
|
const grow = (extent, value) => {
|
|
85
88
|
if (value === null || !Number.isFinite(value)) {
|
|
86
89
|
return;
|
|
@@ -561,7 +564,7 @@ export function buildChartModel({
|
|
|
561
564
|
stacks
|
|
562
565
|
});
|
|
563
566
|
const yAxisModels = yAxes.reduce((built, axis, index) => {
|
|
564
|
-
const hint = axis.tickAmount ?? 5;
|
|
567
|
+
const hint = axis.tickAmount ?? (axis.tickPixelInterval ? Math.max(MIN_Y_TICK_HINT, Math.round(plot.height / axis.tickPixelInterval)) : 5);
|
|
565
568
|
const target = axis.linkedTo === undefined ? undefined : built[axis.linkedTo];
|
|
566
569
|
const range = axis.categories?.length ? [plot.y, plot.y + plot.height] : [plot.y + plot.height, plot.y];
|
|
567
570
|
const scale = buildYScale(axis, yDomains[index] ?? emptyExtent(), range, hint, target?.scale);
|
package/core/model/palette.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const DEFAULT_SURFACE_COLOR: string;
|
|
|
15
15
|
* yet. Two neutrals, not one: white on the mid greys a threshold is painted in
|
|
16
16
|
* reads at 2.8:1, far under the 4.5:1 small text needs.
|
|
17
17
|
*/
|
|
18
|
-
export declare const DEFAULT_ON_FILL_TEXT_COLOR
|
|
18
|
+
export declare const DEFAULT_ON_FILL_TEXT_COLOR = "#FFFFFF";
|
|
19
19
|
/** Whichever of the two neutrals reads better on a fill. */
|
|
20
20
|
export declare function textColorOn(fill: string): string;
|
|
21
21
|
export declare const DEFAULT_TOOLTIP_SURFACE_COLOR: string;
|
package/core/model/palette.js
CHANGED
|
@@ -17,7 +17,9 @@ export const DEFAULT_SURFACE_COLOR = Color.CLEAR;
|
|
|
17
17
|
* yet. Two neutrals, not one: white on the mid greys a threshold is painted in
|
|
18
18
|
* reads at 2.8:1, far under the 4.5:1 small text needs.
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
// Literal white rather than `Color.CLEAR`: the fill is the caller's, so the ink on it
|
|
21
|
+
// must stay readable instead of turning #323233 with the dark theme.
|
|
22
|
+
export const DEFAULT_ON_FILL_TEXT_COLOR = '#FFFFFF';
|
|
21
23
|
const ON_FILL_DARK_TEXT_COLOR = Color.BRAND_BLACK;
|
|
22
24
|
const linearChannel = value => {
|
|
23
25
|
const unit = value / 255;
|
|
@@ -32,15 +34,16 @@ const luminance = color => {
|
|
|
32
34
|
return 0.2126 * linearChannel(rgba[0]) + 0.7152 * linearChannel(rgba[1]) + 0.0722 * linearChannel(rgba[2]);
|
|
33
35
|
};
|
|
34
36
|
const contrast = (one, other) => (Math.max(one, other) + 0.05) / (Math.min(one, other) + 0.05);
|
|
35
|
-
const LIGHT_TEXT_LUMINANCE = luminance(DEFAULT_ON_FILL_TEXT_COLOR) ?? 1;
|
|
36
|
-
const DARK_TEXT_LUMINANCE = luminance(ON_FILL_DARK_TEXT_COLOR) ?? 0;
|
|
37
37
|
/** Whichever of the two neutrals reads better on a fill. */
|
|
38
38
|
export function textColorOn(fill) {
|
|
39
39
|
const behind = luminance(fill);
|
|
40
40
|
if (behind === null) {
|
|
41
41
|
return DEFAULT_ON_FILL_TEXT_COLOR;
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// Read per call, not once: both neutrals are tokens and swap literals when the theme does.
|
|
44
|
+
const light = luminance(DEFAULT_ON_FILL_TEXT_COLOR) ?? 1;
|
|
45
|
+
const dark = luminance(ON_FILL_DARK_TEXT_COLOR) ?? 0;
|
|
46
|
+
return contrast(behind, light) >= contrast(behind, dark) ? DEFAULT_ON_FILL_TEXT_COLOR : ON_FILL_DARK_TEXT_COLOR;
|
|
44
47
|
}
|
|
45
48
|
// Chart tooltips follow the product hint style: dark bubble, light text.
|
|
46
49
|
export const DEFAULT_TOOLTIP_SURFACE_COLOR = Color.BRAND_BLACK;
|
package/core/scale/color.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { type ThemeName } from '@pushwoosh/kit-constants';
|
|
1
2
|
import { type ColorScale, type ColorStop } from '../types/scale';
|
|
2
3
|
export interface ColorScaleOptions {
|
|
3
4
|
domain: readonly [number, number];
|
|
4
5
|
stops: readonly ColorStop[];
|
|
5
6
|
}
|
|
6
7
|
type Rgba = [number, number, number, number];
|
|
8
|
+
/** Theme the page is painted in; a chart reads it the way CSS does, off `<html>`. */
|
|
9
|
+
export declare const activeTheme: () => ThemeName;
|
|
7
10
|
export declare const parseColor: (color: string) => Rgba | null;
|
|
8
11
|
export declare function createColorScale(options: ColorScaleOptions): ColorScale;
|
|
9
12
|
export {};
|
package/core/scale/color.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Color, DEFAULT_THEME, getThemeColors, THEME_ATTRIBUTE } from '@pushwoosh/kit-constants';
|
|
1
2
|
const clampChannel = value => Math.min(255, Math.max(0, Math.round(value)));
|
|
2
3
|
const parseHex = color => {
|
|
3
4
|
const match = /^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(color);
|
|
@@ -21,7 +22,26 @@ const parseFunctional = color => {
|
|
|
21
22
|
}
|
|
22
23
|
return [parts[0], parts[1], parts[2], parts[3] === undefined ? 1 : parts[3]];
|
|
23
24
|
};
|
|
24
|
-
|
|
25
|
+
const TOKEN_OF_VALUE = new Map(Object.keys(Color).filter(token => token !== 'CURRENT').map(token => [Color[token], token]));
|
|
26
|
+
/** Theme the page is painted in; a chart reads it the way CSS does, off `<html>`. */
|
|
27
|
+
export const activeTheme = () => typeof document !== 'undefined' && document.documentElement.getAttribute(THEME_ATTRIBUTE) === 'dark' ? 'dark' : DEFAULT_THEME;
|
|
28
|
+
const unwrapVar = color => {
|
|
29
|
+
const match = /^var\(\s*--[^,)]+,([\s\S]+)\)$/.exec(color);
|
|
30
|
+
return match ? match[1].trim() : null;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Literal behind a design-system colour. Tokens are `var(--pw-color-x, <light hex>)`, whose fallback lies
|
|
34
|
+
* under a dark theme, so a token resolves through the palette and only an unknown `var()` takes its fallback.
|
|
35
|
+
*/
|
|
36
|
+
const resolveColor = color => {
|
|
37
|
+
const token = TOKEN_OF_VALUE.get(color);
|
|
38
|
+
return token ? getThemeColors(activeTheme())[token] : unwrapVar(color);
|
|
39
|
+
};
|
|
40
|
+
export const parseColor = color => {
|
|
41
|
+
const value = color.trim();
|
|
42
|
+
const literal = resolveColor(value);
|
|
43
|
+
return literal !== null ? parseColor(literal) : parseHex(value) ?? parseFunctional(value);
|
|
44
|
+
};
|
|
25
45
|
const toCss = ([r, g, b, a]) => a >= 1 ? `#${[r, g, b].map(channel => clampChannel(channel).toString(16).padStart(2, '0')).join('')}` : `rgba(${clampChannel(r)}, ${clampChannel(g)}, ${clampChannel(b)}, ${Number(a.toFixed(3))})`;
|
|
26
46
|
const mix = (from, to, t) => [from[0] + (to[0] - from[0]) * t, from[1] + (to[1] - from[1]) * t, from[2] + (to[2] - from[2]) * t, from[3] + (to[3] - from[3]) * t];
|
|
27
47
|
// A stop whose colour cannot be parsed still holds its position: it is returned
|
package/core/types/options.d.ts
CHANGED
|
@@ -150,6 +150,7 @@ export interface AxisOptions {
|
|
|
150
150
|
tickLength?: number;
|
|
151
151
|
tickAmount?: number;
|
|
152
152
|
tickInterval?: number | TimeUnit;
|
|
153
|
+
/** Space a tick asks for: across the plot on an x axis, down it on a y one. */
|
|
153
154
|
tickPixelInterval?: number;
|
|
154
155
|
tickPositions?: readonly number[];
|
|
155
156
|
gridLineWidth?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pushwoosh/kit-charts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "Small React chart library on SVG, with a Highcharts-shaped configuration model",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"pre-commit": "check",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@pushwoosh/kit-constants": "^
|
|
38
|
+
"@pushwoosh/kit-constants": "^2.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@pushwoosh/frontend-builder-engine": "^3.1.0",
|
|
@@ -59,6 +59,6 @@
|
|
|
59
59
|
"styled-components": ">=5.3.3"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
|
-
"node": ">=
|
|
62
|
+
"node": ">= 24"
|
|
63
63
|
}
|
|
64
64
|
}
|