@pushwoosh/kit-charts 0.0.5 → 0.0.6
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
CHANGED
|
@@ -339,12 +339,15 @@ the value wrapped in `valuePrefix`/`valueSuffix`. `formatter` replaces the body
|
|
|
339
339
|
returns a `ReactNode`; `ctx.points[].prev`/`.next` carry the neighbouring points, so
|
|
340
340
|
a delta needs no extra lookup. `shared: true` collects every series at the hovered x.
|
|
341
341
|
|
|
342
|
-
`headerFormat` and `pointFormatter` are taken under their Highcharts
|
|
343
|
-
config that already carries them needs no rewrite: `headerFormat: ''`
|
|
344
|
-
|
|
345
|
-
`{
|
|
346
|
-
|
|
347
|
-
`
|
|
342
|
+
`headerFormat`, `pointFormat` and `pointFormatter` are taken under their Highcharts
|
|
343
|
+
names, so a config that already carries them needs no rewrite: `headerFormat: ''`
|
|
344
|
+
drops the header and `pointFormat` writes the row after the swatch. Both templates
|
|
345
|
+
fill `{point.key}`, `{point.x}`, `{point.y}`, `{point.value}` and `{series.name}`,
|
|
346
|
+
date an x through `{point.x:%b %d}` (a padded pattern is trimmed) and pass numbers
|
|
347
|
+
through the chart's `numberFormat`; markup in them is dropped, because the chrome
|
|
348
|
+
around a tooltip is the library's. `pointFormatter` is handed the point and returns
|
|
349
|
+
a `ReactNode`, and outranks `pointFormat`; `formatter` and `table` outrank all
|
|
350
|
+
three. Golden cases: `area/header-format`, `line/point-format-template`.
|
|
348
351
|
|
|
349
352
|
`ctx.points[].pointMeta` is the hovered point's own `meta` — the third type
|
|
350
353
|
parameter of `ChartOptions<TChartMeta, TSeriesMeta, TPointMeta>`, the same object
|
package/core/Chart/Chart.js
CHANGED
|
@@ -33,32 +33,47 @@ const toCssSize = (value, fallback) => {
|
|
|
33
33
|
}
|
|
34
34
|
return typeof value === 'number' ? `${value}px` : value;
|
|
35
35
|
};
|
|
36
|
-
|
|
36
|
+
const templateContext = (point, x) => ({
|
|
37
|
+
x,
|
|
38
|
+
y: point?.y ?? null,
|
|
39
|
+
value: point?.value ?? null,
|
|
40
|
+
seriesName: point?.seriesName ?? ''
|
|
41
|
+
});
|
|
42
|
+
function tooltipHeader(ctx, headerFormat, formatX, numberFormat) {
|
|
37
43
|
if (headerFormat === undefined) {
|
|
38
44
|
return formatX(ctx.x);
|
|
39
45
|
}
|
|
40
|
-
return applyTooltipTemplate(headerFormat,
|
|
41
|
-
x: ctx.x,
|
|
42
|
-
y: ctx.points[0]?.y ?? null,
|
|
43
|
-
seriesName: ctx.points[0]?.seriesName ?? ''
|
|
44
|
-
});
|
|
46
|
+
return applyTooltipTemplate(headerFormat, templateContext(ctx.points[0], ctx.x), numberFormat);
|
|
45
47
|
}
|
|
46
|
-
function
|
|
47
|
-
const header = tooltipHeader(ctx, tooltip?.headerFormat, formatX);
|
|
48
|
+
function pointRow(point, tooltip, formatValue, numberFormat) {
|
|
48
49
|
const pointFormatter = tooltip?.pointFormatter;
|
|
50
|
+
if (pointFormatter) {
|
|
51
|
+
return pointFormatter(point);
|
|
52
|
+
}
|
|
53
|
+
if (tooltip?.pointFormat !== undefined) {
|
|
54
|
+
return _jsxs(_Fragment, {
|
|
55
|
+
children: [_jsx(TooltipSwatch, {
|
|
56
|
+
"$color": point.color
|
|
57
|
+
}), applyTooltipTemplate(tooltip.pointFormat, templateContext(point, point.x), numberFormat)]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return _jsxs(_Fragment, {
|
|
61
|
+
children: [_jsx(TooltipSwatch, {
|
|
62
|
+
"$color": point.color
|
|
63
|
+
}), _jsx(TooltipName, {
|
|
64
|
+
children: point.seriesName
|
|
65
|
+
}), _jsx(TooltipValue, {
|
|
66
|
+
children: formatValue(point.value ?? point.y)
|
|
67
|
+
})]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function defaultTooltip(ctx, tooltip, formatX, formatValue, numberFormat) {
|
|
71
|
+
const header = tooltipHeader(ctx, tooltip?.headerFormat, formatX, numberFormat);
|
|
49
72
|
return _jsxs("div", {
|
|
50
73
|
children: [header ? _jsx(TooltipTitle, {
|
|
51
74
|
children: header
|
|
52
75
|
}) : null, ctx.points.map(point => _jsx(TooltipRow, {
|
|
53
|
-
children:
|
|
54
|
-
children: [_jsx(TooltipSwatch, {
|
|
55
|
-
"$color": point.color
|
|
56
|
-
}), _jsx(TooltipName, {
|
|
57
|
-
children: point.seriesName
|
|
58
|
-
}), _jsx(TooltipValue, {
|
|
59
|
-
children: formatValue(point.value ?? point.y)
|
|
60
|
-
})]
|
|
61
|
-
})
|
|
76
|
+
children: pointRow(point, tooltip, formatValue, numberFormat)
|
|
62
77
|
}, `${point.seriesIndex}-${point.index}`))]
|
|
63
78
|
});
|
|
64
79
|
}
|
|
@@ -450,7 +465,7 @@ function ChartBody({
|
|
|
450
465
|
return formatter(ctx);
|
|
451
466
|
}
|
|
452
467
|
const table = options.tooltip?.table;
|
|
453
|
-
return table ? tableTooltip(ctx, table, formatX) : defaultTooltip(ctx, options.tooltip, formatX, formatValue);
|
|
468
|
+
return table ? tableTooltip(ctx, table, formatX) : defaultTooltip(ctx, options.tooltip, formatX, formatValue, model.numberFormat);
|
|
454
469
|
}, [hover, model, options.title?.text, options.meta, options.tooltip, formatX, formatValue]);
|
|
455
470
|
const hasData = model?.series.some(series => series.points.some(point => point.y !== null)) ?? false;
|
|
456
471
|
const plotBorderWidth = options.chart?.plotBorderWidth ?? 0;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { type NumberFormatter } from '../types/renderer';
|
|
1
2
|
export interface TemplateContext {
|
|
2
3
|
x: number | string;
|
|
3
4
|
y: number | null;
|
|
5
|
+
value: number | null;
|
|
4
6
|
seriesName: string;
|
|
5
7
|
}
|
|
6
8
|
/**
|
|
7
|
-
* Fills a Highcharts header template. Markup in it is dropped rather than
|
|
8
|
-
* the chrome around a tooltip is the library's, and a `<span>`
|
|
9
|
+
* Fills a Highcharts header or point template. Markup in it is dropped rather than
|
|
10
|
+
* rendered: the chrome around a tooltip is the library's, and a `<span>` is styling.
|
|
9
11
|
*/
|
|
10
|
-
export declare function applyTooltipTemplate(format: string, ctx: TemplateContext): string;
|
|
12
|
+
export declare function applyTooltipTemplate(format: string, ctx: TemplateContext, numberFormat?: NumberFormatter): string;
|
package/core/format/template.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { formatTime } from './time';
|
|
2
2
|
import { fillTokens } from './tokens';
|
|
3
|
-
const substitute = (name, ctx) => {
|
|
3
|
+
const substitute = (name, ctx, numberFormat) => {
|
|
4
4
|
switch (name) {
|
|
5
5
|
case 'point.key':
|
|
6
6
|
case 'point.x':
|
|
7
7
|
return String(ctx.x);
|
|
8
8
|
case 'point.y':
|
|
9
|
-
return ctx.y === null ? '' :
|
|
9
|
+
return ctx.y === null ? '' : numberFormat(ctx.y);
|
|
10
|
+
case 'point.value':
|
|
11
|
+
return ctx.value === null ? '' : numberFormat(ctx.value);
|
|
10
12
|
case 'series.name':
|
|
11
13
|
return ctx.seriesName;
|
|
12
14
|
default:
|
|
@@ -14,13 +16,13 @@ const substitute = (name, ctx) => {
|
|
|
14
16
|
}
|
|
15
17
|
};
|
|
16
18
|
/**
|
|
17
|
-
* Fills a Highcharts header template. Markup in it is dropped rather than
|
|
18
|
-
* the chrome around a tooltip is the library's, and a `<span>`
|
|
19
|
+
* Fills a Highcharts header or point template. Markup in it is dropped rather than
|
|
20
|
+
* rendered: the chrome around a tooltip is the library's, and a `<span>` is styling.
|
|
19
21
|
*/
|
|
20
|
-
export function applyTooltipTemplate(format, ctx) {
|
|
22
|
+
export function applyTooltipTemplate(format, ctx, numberFormat = String) {
|
|
21
23
|
const stripped = format.replace(/<br\s*\/?>/gi, ' ').replace(/<[^>]*>/g, '');
|
|
22
24
|
return fillTokens(stripped, (name, pattern) => {
|
|
23
|
-
const value = substitute(name, ctx);
|
|
25
|
+
const value = substitute(name, ctx, numberFormat);
|
|
24
26
|
if (value === undefined) {
|
|
25
27
|
return undefined;
|
|
26
28
|
}
|
package/core/format/tokens.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type TokenResolver = (name: string, pattern: string | undefined) => string | undefined;
|
|
2
|
-
/** Fills `{name}` and `{name:pattern}
|
|
2
|
+
/** Fills `{name}` and `{name:pattern}`; an unresolved token is left as it stands. */
|
|
3
3
|
export declare function fillTokens(format: string, resolve: TokenResolver): string;
|
package/core/format/tokens.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const TOKEN = /\{([a-z][a-z.]*)(?::([^}]*))?\}/gi;
|
|
2
|
-
/** Fills `{name}` and `{name:pattern}
|
|
2
|
+
/** Fills `{name}` and `{name:pattern}`; an unresolved token is left as it stands. */
|
|
3
3
|
export function fillTokens(format, resolve) {
|
|
4
|
-
return format.replace(TOKEN, (match, name, pattern) => resolve(name, pattern) ?? match);
|
|
4
|
+
return format.replace(TOKEN, (match, name, pattern) => resolve(name, pattern?.trim() || undefined) ?? match);
|
|
5
5
|
}
|
package/core/types/options.d.ts
CHANGED
|
@@ -207,6 +207,8 @@ export interface TooltipOptions<TChartMeta = unknown, TSeriesMeta = unknown, TPo
|
|
|
207
207
|
formatter?: TooltipFormatter<TChartMeta, TSeriesMeta, TPointMeta>;
|
|
208
208
|
/** Highcharts' header template: `''` drops the header, `{point.key}` and friends fill. */
|
|
209
209
|
headerFormat?: string;
|
|
210
|
+
/** Highcharts' per-point template, drawn after the swatch; `pointFormatter` wins. */
|
|
211
|
+
pointFormat?: string;
|
|
210
212
|
/** One row per point, in place of the default swatch, name and value. */
|
|
211
213
|
pointFormatter?: TooltipCellFormatter<TSeriesMeta, TPointMeta>;
|
|
212
214
|
dateFormat?: string;
|