@aurum-grid/charts 0.0.0-stage → 0.2.0
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/LICENSE.md +24 -0
- package/README.md +6 -2
- package/dist/chart.d.ts +146 -0
- package/dist/chart.js +1158 -0
- package/dist/chart.js.map +1 -0
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +54 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/dist/integrated.d.ts +78 -0
- package/dist/integrated.js +563 -0
- package/dist/integrated.js.map +1 -0
- package/dist/smart.d.ts +17 -0
- package/dist/smart.js +121 -0
- package/dist/smart.js.map +1 -0
- package/dist/sparkline.d.ts +14 -0
- package/dist/sparkline.js +61 -0
- package/dist/sparkline.js.map +1 -0
- package/dist/studio.d.ts +50 -0
- package/dist/studio.js +271 -0
- package/dist/studio.js.map +1 -0
- package/dist/styles.css +221 -0
- package/dist/transform.d.ts +62 -0
- package/dist/transform.js +274 -0
- package/dist/transform.js.map +1 -0
- package/package.json +37 -3
package/dist/smart.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { toNumber, linearRegression, holtForecast, nextLabels, compactNumber, extremes } from './transform.js';
|
|
2
|
+
import { CHART_TYPES, looksLikeTime } from './chart.js';
|
|
3
|
+
/**
|
|
4
|
+
* Rank chart types for a category × measures dataset. Scores are transparent heuristics:
|
|
5
|
+
* time axis, number of categories and series, negative values, scale difference between
|
|
6
|
+
* measures, and whether a part-to-whole reading makes sense.
|
|
7
|
+
*/
|
|
8
|
+
export function recommendCharts(data, categoryKey, seriesKeys) {
|
|
9
|
+
const labels = data.map((d) => String(d[categoryKey] ?? ''));
|
|
10
|
+
const n = labels.length;
|
|
11
|
+
const s = seriesKeys.length;
|
|
12
|
+
const values = seriesKeys.map((k) => data.map((d) => toNumber(d[k])));
|
|
13
|
+
const all = values.flat();
|
|
14
|
+
const hasNeg = all.some((v) => v < 0);
|
|
15
|
+
const allPos = all.every((v) => v >= 0);
|
|
16
|
+
const time = looksLikeTime(labels);
|
|
17
|
+
const longLabels = Math.max(0, ...labels.map((l) => l.length)) > 12;
|
|
18
|
+
const maxes = values.map((v) => Math.max(...v.map(Math.abs), 1e-9));
|
|
19
|
+
const ratio = s >= 2 ? Math.max(...maxes) / Math.min(...maxes) : 1;
|
|
20
|
+
const out = [];
|
|
21
|
+
const add = (type, score, reason) => score > 0 && out.push({ type, score: Math.round(Math.min(99, score)), reason });
|
|
22
|
+
if (time) {
|
|
23
|
+
add('line', 92, `${n} time periods — a line shows the trend and supports forecasting.`);
|
|
24
|
+
add('area', allPos && s <= 3 ? 76 : 40, 'Emphasises volume over time; best with positive values.');
|
|
25
|
+
add('column', 70, 'Columns also work for periods when you compare individual months.');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
add('column', n <= 12 ? (s === 1 ? 88 : 86) : 62, s === 1 ? `Compares one measure across ${n} categories.` : 'Grouped columns compare several measures per category.');
|
|
29
|
+
add('bar', n > 8 || longLabels ? 87 : 68, n > 8 || longLabels ? 'Many categories or long labels read better horizontally.' : 'Horizontal bars sort cleanly by size.');
|
|
30
|
+
}
|
|
31
|
+
if (s >= 2) {
|
|
32
|
+
add('combo', ratio > 8 ? 91 : 66, ratio > 8 ? `The measures differ about ${Math.round(ratio)}× in scale — bars plus a line on a second axis keep both readable.` : 'Bars for one measure, a line for another.');
|
|
33
|
+
if (allPos) {
|
|
34
|
+
add('stackedColumn', 80, 'Stacked columns show the total and its parts.');
|
|
35
|
+
add('normalizedColumn', 64, '100% stacks compare the mix across categories.');
|
|
36
|
+
}
|
|
37
|
+
if (n >= 3 && n <= 8)
|
|
38
|
+
add('radar', 52, 'Compares a profile of measures; normalise when units differ.');
|
|
39
|
+
add('scatter', s >= 2 && n >= 8 ? 50 : 30, 'Shows the relationship between two measures.');
|
|
40
|
+
}
|
|
41
|
+
if (s === 1) {
|
|
42
|
+
if (allPos && n <= 6) {
|
|
43
|
+
add('donut', 84, `Part-to-whole with ${n} categories.`);
|
|
44
|
+
add('pie', 80, `Part-to-whole with ${n} categories.`);
|
|
45
|
+
}
|
|
46
|
+
else if (allPos && n <= 10)
|
|
47
|
+
add('donut', 52, 'Part-to-whole works, but more than six slices are hard to compare.');
|
|
48
|
+
if (hasNeg)
|
|
49
|
+
add('waterfall', 78, 'Positive and negative contributions add up to a total.');
|
|
50
|
+
if (allPos && n >= 6)
|
|
51
|
+
add('treemap', 68, 'Shows relative size across many categories.');
|
|
52
|
+
if (allPos && !time)
|
|
53
|
+
add('funnel', 30, 'Only meaningful when categories are ordered stages.');
|
|
54
|
+
}
|
|
55
|
+
if (hasNeg) {
|
|
56
|
+
for (const r of out)
|
|
57
|
+
if (r.type === 'pie' || r.type === 'donut' || r.type === 'treemap')
|
|
58
|
+
r.score = 0;
|
|
59
|
+
}
|
|
60
|
+
return out
|
|
61
|
+
.filter((r) => r.score > 0)
|
|
62
|
+
.sort((a, b) => b.score - a.score)
|
|
63
|
+
.map((r) => ({ ...r, label: CHART_TYPES.find((t) => t.value === r.type)?.label ?? r.type }));
|
|
64
|
+
}
|
|
65
|
+
/** Plain-language description of what a chart shows (deterministic). */
|
|
66
|
+
export function explainChart(o, fmt = compactNumber) {
|
|
67
|
+
if (!o.data.length || !o.series.length)
|
|
68
|
+
return 'There is no data in this chart yet.';
|
|
69
|
+
const s = o.series[0];
|
|
70
|
+
const name = s.name ?? s.key;
|
|
71
|
+
const labels = o.data.map((d) => String(d[o.categoryKey] ?? ''));
|
|
72
|
+
const vals = o.data.map((d) => toNumber(d[s.key]));
|
|
73
|
+
const parts = [];
|
|
74
|
+
const typeLabel = CHART_TYPES.find((t) => t.value === o.type)?.label ?? o.type;
|
|
75
|
+
if (o.type === 'gauge') {
|
|
76
|
+
const v = vals[0];
|
|
77
|
+
parts.push(`${name} is ${fmt(v)}${o.max ? ` out of ${fmt(o.max)}` : ''}.`);
|
|
78
|
+
if (o.target != null)
|
|
79
|
+
parts.push(v >= o.target ? `That meets the ${fmt(o.target)} target.` : `That is ${fmt(o.target - v)} below the ${fmt(o.target)} target.`);
|
|
80
|
+
return parts.join(' ');
|
|
81
|
+
}
|
|
82
|
+
if (o.type === 'funnel') {
|
|
83
|
+
const first = vals[0] || 1;
|
|
84
|
+
const last = vals[vals.length - 1];
|
|
85
|
+
let worst = 1;
|
|
86
|
+
for (let i = 1; i < vals.length; i++)
|
|
87
|
+
if (vals[i] / (vals[i - 1] || 1) < vals[worst] / (vals[worst - 1] || 1))
|
|
88
|
+
worst = i;
|
|
89
|
+
parts.push(`${labels[0]} to ${labels[labels.length - 1]} converts ${((last / first) * 100).toFixed(0)}% overall.`);
|
|
90
|
+
if (vals.length > 1)
|
|
91
|
+
parts.push(`The biggest drop is ${labels[worst - 1]} → ${labels[worst]} (${((vals[worst] / (vals[worst - 1] || 1)) * 100).toFixed(0)}% carried through).`);
|
|
92
|
+
return parts.join(' ');
|
|
93
|
+
}
|
|
94
|
+
const total = vals.reduce((a, b) => a + b, 0);
|
|
95
|
+
const { maxIndex, minIndex } = extremes(vals);
|
|
96
|
+
parts.push(`${typeLabel} chart of ${name} across ${labels.length} ${looksLikeTime(labels) ? 'periods' : 'categories'}.`);
|
|
97
|
+
if (maxIndex >= 0)
|
|
98
|
+
parts.push(`Highest: ${labels[maxIndex]} at ${fmt(vals[maxIndex])}. Lowest: ${labels[minIndex]} at ${fmt(vals[minIndex])}.`);
|
|
99
|
+
if (['pie', 'donut', 'treemap', 'column', 'bar'].includes(o.type) && vals.every((v) => v >= 0) && total > 0 && maxIndex >= 0) {
|
|
100
|
+
parts.push(`${labels[maxIndex]} is ${((vals[maxIndex] / total) * 100).toFixed(0)}% of the total ${fmt(total)}.`);
|
|
101
|
+
}
|
|
102
|
+
else if (vals.some((v) => v < 0)) {
|
|
103
|
+
parts.push(`${vals.filter((v) => v < 0).length} of ${vals.length} values are negative; the net total is ${fmt(total)}.`);
|
|
104
|
+
}
|
|
105
|
+
if (looksLikeTime(labels) && vals.length >= 3) {
|
|
106
|
+
const reg = linearRegression(vals);
|
|
107
|
+
const dir = Math.abs(reg.slope) < Math.abs(total / vals.length) * 0.01 ? 'is roughly flat' : reg.slope > 0 ? `is rising by about ${fmt(reg.slope)} per period` : `is falling by about ${fmt(Math.abs(reg.slope))} per period`;
|
|
108
|
+
parts.push(`The trend ${dir} (R² ${reg.r2.toFixed(2)}${reg.r2 < 0.3 ? ', a weak fit' : ''}).`);
|
|
109
|
+
if (o.forecast) {
|
|
110
|
+
const fc = holtForecast(vals, o.forecast);
|
|
111
|
+
const fl = nextLabels(labels, fc.length);
|
|
112
|
+
parts.push(`Forecast: ${fc.map((p, i) => `${fl[i]} ${fmt(p.value)}`).join(', ')} (shaded band is an approximate 95% range).`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (o.series.length > 1)
|
|
116
|
+
parts.push(`Also shows ${o.series.slice(1).map((x) => x.name ?? x.key).join(', ')}.`);
|
|
117
|
+
if (o.referenceLines?.length)
|
|
118
|
+
parts.push(`Reference line${o.referenceLines.length > 1 ? 's' : ''}: ${o.referenceLines.map((r) => `${r.label ?? 'line'} at ${fmt(r.value)}`).join(', ')}.`);
|
|
119
|
+
return parts.join(' ');
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=smart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart.js","sourceRoot":"","sources":["../src/smart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SparklineOptions {
|
|
2
|
+
width?: number;
|
|
3
|
+
height?: number;
|
|
4
|
+
/** Colour rising/falling lines with the theme's success/danger tokens. */
|
|
5
|
+
trendColors?: boolean;
|
|
6
|
+
area?: boolean;
|
|
7
|
+
format?: (v: number) => string;
|
|
8
|
+
}
|
|
9
|
+
/** Tiny inline SVG line chart with an emphasised last point. */
|
|
10
|
+
export declare function createSparkline(values: unknown[], o?: SparklineOptions): SVGSVGElement;
|
|
11
|
+
/** Grid cell renderer: `cellRenderer: sparklineRenderer({ width: 90 })` on an array-valued column. */
|
|
12
|
+
export declare function sparklineRenderer(o?: SparklineOptions): (params: {
|
|
13
|
+
value: unknown;
|
|
14
|
+
}) => HTMLSpanElement;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { toNumber } from './transform.js';
|
|
2
|
+
const NS = 'http://www.w3.org/2000/svg';
|
|
3
|
+
/** Tiny inline SVG line chart with an emphasised last point. */
|
|
4
|
+
export function createSparkline(values, o = {}) {
|
|
5
|
+
const w = o.width ?? 96;
|
|
6
|
+
const h = o.height ?? 22;
|
|
7
|
+
const vals = values.map(toNumber);
|
|
8
|
+
const svgEl = document.createElementNS(NS, 'svg');
|
|
9
|
+
svgEl.setAttribute('viewBox', `0 0 ${w} ${h}`);
|
|
10
|
+
svgEl.setAttribute('width', String(w));
|
|
11
|
+
svgEl.setAttribute('height', String(h));
|
|
12
|
+
svgEl.setAttribute('class', 'agc-spark');
|
|
13
|
+
svgEl.setAttribute('role', 'img');
|
|
14
|
+
if (vals.length < 2) {
|
|
15
|
+
svgEl.setAttribute('aria-label', 'Not enough history');
|
|
16
|
+
return svgEl;
|
|
17
|
+
}
|
|
18
|
+
const lo = Math.min(...vals);
|
|
19
|
+
const hi = Math.max(...vals);
|
|
20
|
+
const x = (i) => 1 + (i / (vals.length - 1)) * (w - 4);
|
|
21
|
+
const y = (v) => (hi === lo ? h / 2 : 2 + (1 - (v - lo) / (hi - lo)) * (h - 4));
|
|
22
|
+
const first = vals[0];
|
|
23
|
+
const last = vals[vals.length - 1];
|
|
24
|
+
const up = last >= first;
|
|
25
|
+
const color = o.trendColors === false ? 'var(--agr-accent)' : up ? 'var(--agr-success)' : 'var(--agr-danger)';
|
|
26
|
+
const d = vals.map((v, i) => `${i ? 'L' : 'M'}${x(i).toFixed(1)},${y(v).toFixed(1)}`).join('');
|
|
27
|
+
if (o.area !== false) {
|
|
28
|
+
const a = document.createElementNS(NS, 'path');
|
|
29
|
+
a.setAttribute('d', `${d}L${x(vals.length - 1)},${h}L${x(0)},${h}Z`);
|
|
30
|
+
a.setAttribute('class', 'agc-spark-area');
|
|
31
|
+
a.style.fill = color;
|
|
32
|
+
svgEl.append(a);
|
|
33
|
+
}
|
|
34
|
+
const p = document.createElementNS(NS, 'path');
|
|
35
|
+
p.setAttribute('d', d);
|
|
36
|
+
p.setAttribute('class', 'agc-spark-line');
|
|
37
|
+
p.style.stroke = color;
|
|
38
|
+
const c = document.createElementNS(NS, 'circle');
|
|
39
|
+
c.setAttribute('cx', String(x(vals.length - 1)));
|
|
40
|
+
c.setAttribute('cy', String(y(last)));
|
|
41
|
+
c.setAttribute('r', '2.2');
|
|
42
|
+
c.style.fill = color;
|
|
43
|
+
svgEl.append(p, c);
|
|
44
|
+
const f = o.format ?? ((v) => v.toFixed(2));
|
|
45
|
+
const pct = first ? ((last - first) / Math.abs(first)) * 100 : 0;
|
|
46
|
+
svgEl.setAttribute('aria-label', `Trend ${up ? 'up' : 'down'} ${Math.abs(pct).toFixed(1)}%: from ${f(first)} to ${f(last)}, range ${f(lo)} to ${f(hi)}`);
|
|
47
|
+
return svgEl;
|
|
48
|
+
}
|
|
49
|
+
/** Grid cell renderer: `cellRenderer: sparklineRenderer({ width: 90 })` on an array-valued column. */
|
|
50
|
+
export function sparklineRenderer(o = {}) {
|
|
51
|
+
return (params) => {
|
|
52
|
+
const wrap = document.createElement('span');
|
|
53
|
+
wrap.className = 'agc-spark-cell';
|
|
54
|
+
const v = Array.isArray(params.value) ? params.value : [];
|
|
55
|
+
const svgEl = createSparkline(v, o);
|
|
56
|
+
wrap.append(svgEl);
|
|
57
|
+
wrap.title = svgEl.getAttribute('aria-label') ?? '';
|
|
58
|
+
return wrap;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=sparkline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sparkline.js","sourceRoot":"","sources":["../src/sparkline.ts"],"names":[],"mappings":"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"}
|
package/dist/studio.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Chart, type ChartOptions, type ChartType } from './chart.js';
|
|
2
|
+
export type StudioTool = 'customize' | 'data' | 'svg' | 'png' | 'explain' | 'trend' | 'forecast' | 'highlights' | 'bestFit' | 'labels';
|
|
3
|
+
export interface ChartStudioOptions {
|
|
4
|
+
chart: ChartOptions;
|
|
5
|
+
/** Chart types offered in the "Chart:" selector. */
|
|
6
|
+
types?: ChartType[];
|
|
7
|
+
tools?: StudioTool[];
|
|
8
|
+
/** Base file name for SVG/PNG exports. */
|
|
9
|
+
fileName?: string;
|
|
10
|
+
/** How to hand a file to the user. Defaults to an <a download> click. */
|
|
11
|
+
download?: (fileName: string, blob: Blob) => void | Promise<void>;
|
|
12
|
+
/** Called whenever the user changes the chart through the studio. */
|
|
13
|
+
onChange?: (options: ChartOptions) => void;
|
|
14
|
+
forecastPeriods?: number;
|
|
15
|
+
idPrefix?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A chart with an aligned toolbar ("Chart: [type]" + actions) and smart tools:
|
|
19
|
+
* Customize, Show data, SVG/PNG export, Explain, Trend, Forecast, Highlights and Best fit.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ChartStudio {
|
|
22
|
+
readonly root: HTMLDivElement;
|
|
23
|
+
readonly chart: Chart;
|
|
24
|
+
private note;
|
|
25
|
+
private dataWrap;
|
|
26
|
+
private customize;
|
|
27
|
+
private typeSelect;
|
|
28
|
+
private toggles;
|
|
29
|
+
private o;
|
|
30
|
+
private id;
|
|
31
|
+
private chartHost;
|
|
32
|
+
constructor(container: HTMLElement, opts: ChartStudioOptions);
|
|
33
|
+
get options(): ChartOptions;
|
|
34
|
+
/** Replace data/options from outside (e.g. when the grid selection changes). */
|
|
35
|
+
update(patch: Partial<ChartOptions>): void;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
private apply;
|
|
38
|
+
private syncToggles;
|
|
39
|
+
private button;
|
|
40
|
+
private toggle;
|
|
41
|
+
private say;
|
|
42
|
+
explain(): void;
|
|
43
|
+
bestFit(): void;
|
|
44
|
+
private showData;
|
|
45
|
+
private fileBase;
|
|
46
|
+
exportSvg(): void;
|
|
47
|
+
exportPng(): Promise<void>;
|
|
48
|
+
private buildCustomize;
|
|
49
|
+
}
|
|
50
|
+
export declare function createChartStudio(container: HTMLElement, opts: ChartStudioOptions): ChartStudio;
|
package/dist/studio.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { Chart, CHART_TYPES, PALETTES } from './chart.js';
|
|
2
|
+
import { explainChart, recommendCharts } from './smart.js';
|
|
3
|
+
const DEFAULT_TOOLS = ['customize', 'data', 'svg', 'png', 'explain', 'trend', 'forecast', 'highlights', 'bestFit'];
|
|
4
|
+
function defaultDownload(fileName, blob) {
|
|
5
|
+
const url = URL.createObjectURL(blob);
|
|
6
|
+
const a = document.createElement('a');
|
|
7
|
+
a.href = url;
|
|
8
|
+
a.download = fileName;
|
|
9
|
+
a.style.display = 'none';
|
|
10
|
+
document.body.append(a);
|
|
11
|
+
a.click();
|
|
12
|
+
a.remove();
|
|
13
|
+
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
14
|
+
}
|
|
15
|
+
let seq = 0;
|
|
16
|
+
/**
|
|
17
|
+
* A chart with an aligned toolbar ("Chart: [type]" + actions) and smart tools:
|
|
18
|
+
* Customize, Show data, SVG/PNG export, Explain, Trend, Forecast, Highlights and Best fit.
|
|
19
|
+
*/
|
|
20
|
+
export class ChartStudio {
|
|
21
|
+
root;
|
|
22
|
+
chart;
|
|
23
|
+
note;
|
|
24
|
+
dataWrap;
|
|
25
|
+
customize;
|
|
26
|
+
typeSelect;
|
|
27
|
+
toggles = new Map();
|
|
28
|
+
o;
|
|
29
|
+
id;
|
|
30
|
+
chartHost;
|
|
31
|
+
constructor(container, opts) {
|
|
32
|
+
this.o = { ...opts };
|
|
33
|
+
this.id = opts.idPrefix ?? `agc-studio-${++seq}`;
|
|
34
|
+
const tools = new Set(opts.tools ?? DEFAULT_TOOLS);
|
|
35
|
+
this.root = document.createElement('div');
|
|
36
|
+
this.root.className = 'agc-studio';
|
|
37
|
+
// toolbar row 1: Chart: [type] … primary actions
|
|
38
|
+
const bar = el('div', 'agc-toolbar');
|
|
39
|
+
bar.setAttribute('role', 'toolbar');
|
|
40
|
+
bar.setAttribute('aria-label', 'Chart controls');
|
|
41
|
+
const field = el('span', 'agc-field');
|
|
42
|
+
const label = document.createElement('label');
|
|
43
|
+
label.className = 'agc-field-label';
|
|
44
|
+
label.htmlFor = `${this.id}-type`;
|
|
45
|
+
label.textContent = 'Chart:';
|
|
46
|
+
this.typeSelect = document.createElement('select');
|
|
47
|
+
this.typeSelect.id = `${this.id}-type`;
|
|
48
|
+
this.typeSelect.className = 'agc-control';
|
|
49
|
+
for (const t of CHART_TYPES.filter((x) => !opts.types || opts.types.includes(x.value))) {
|
|
50
|
+
const op = document.createElement('option');
|
|
51
|
+
op.value = t.value;
|
|
52
|
+
op.textContent = t.label;
|
|
53
|
+
this.typeSelect.append(op);
|
|
54
|
+
}
|
|
55
|
+
this.typeSelect.value = opts.chart.type;
|
|
56
|
+
this.typeSelect.addEventListener('change', () => this.apply({ type: this.typeSelect.value }));
|
|
57
|
+
field.append(label, this.typeSelect);
|
|
58
|
+
const g1 = el('div', 'agc-toolbar-group');
|
|
59
|
+
g1.append(field);
|
|
60
|
+
const g2 = el('div', 'agc-toolbar-group');
|
|
61
|
+
if (tools.has('customize'))
|
|
62
|
+
g2.append(this.toggle('customize', 'Customize', (on) => (this.customize.hidden = !on)));
|
|
63
|
+
if (tools.has('data'))
|
|
64
|
+
g2.append(this.toggle('data', 'Show data', (on) => this.showData(on)));
|
|
65
|
+
if (tools.has('svg'))
|
|
66
|
+
g2.append(this.button('SVG', 'Download as SVG', () => this.exportSvg()));
|
|
67
|
+
if (tools.has('png'))
|
|
68
|
+
g2.append(this.button('PNG', 'Download as PNG', () => void this.exportPng()));
|
|
69
|
+
bar.append(g1, g2);
|
|
70
|
+
// toolbar row 2: smart tools
|
|
71
|
+
const bar2 = el('div', 'agc-toolbar agc-toolbar-smart');
|
|
72
|
+
bar2.setAttribute('role', 'toolbar');
|
|
73
|
+
bar2.setAttribute('aria-label', 'Chart insights');
|
|
74
|
+
const g3 = el('div', 'agc-toolbar-group');
|
|
75
|
+
if (tools.has('explain'))
|
|
76
|
+
g3.append(this.button('Explain', 'Describe this chart in words', () => this.explain()));
|
|
77
|
+
if (tools.has('trend'))
|
|
78
|
+
g3.append(this.toggle('trend', 'Trend', (on) => this.apply({ trendline: on })));
|
|
79
|
+
if (tools.has('forecast'))
|
|
80
|
+
g3.append(this.toggle('forecast', 'Forecast', (on) => this.apply({ forecast: on ? (this.o.forecastPeriods ?? 3) : 0 })));
|
|
81
|
+
if (tools.has('highlights'))
|
|
82
|
+
g3.append(this.toggle('highlights', 'Highlights', (on) => this.apply({ highlights: on })));
|
|
83
|
+
if (tools.has('labels'))
|
|
84
|
+
g3.append(this.toggle('labels', 'Data labels', (on) => this.apply({ dataLabels: on })));
|
|
85
|
+
if (tools.has('bestFit'))
|
|
86
|
+
g3.append(this.button('Best fit', 'Switch to the recommended chart type', () => this.bestFit()));
|
|
87
|
+
if (g3.childElementCount)
|
|
88
|
+
bar2.append(g3);
|
|
89
|
+
this.customize = this.buildCustomize();
|
|
90
|
+
this.customize.hidden = true;
|
|
91
|
+
this.note = el('div', 'agc-note');
|
|
92
|
+
this.note.setAttribute('role', 'status');
|
|
93
|
+
this.note.setAttribute('aria-live', 'polite');
|
|
94
|
+
this.note.hidden = true;
|
|
95
|
+
this.chartHost = el('div', 'agc-studio-chart');
|
|
96
|
+
this.dataWrap = el('div', 'agc-data-wrap');
|
|
97
|
+
this.dataWrap.hidden = true;
|
|
98
|
+
this.root.append(bar, ...(bar2.childElementCount ? [bar2] : []), this.customize, this.note, this.chartHost, this.dataWrap);
|
|
99
|
+
container.append(this.root);
|
|
100
|
+
if (opts.chart.height === 'fill')
|
|
101
|
+
this.root.classList.add('agc-studio-fill');
|
|
102
|
+
this.chart = new Chart(this.chartHost, opts.chart);
|
|
103
|
+
this.syncToggles();
|
|
104
|
+
}
|
|
105
|
+
get options() {
|
|
106
|
+
return this.chart.options;
|
|
107
|
+
}
|
|
108
|
+
/** Replace data/options from outside (e.g. when the grid selection changes). */
|
|
109
|
+
update(patch) {
|
|
110
|
+
this.chart.update(patch);
|
|
111
|
+
if (patch.type)
|
|
112
|
+
this.typeSelect.value = patch.type;
|
|
113
|
+
this.syncToggles();
|
|
114
|
+
if (!this.dataWrap.hidden)
|
|
115
|
+
this.showData(true);
|
|
116
|
+
if (!this.note.hidden && this.note.dataset.kind === 'explain')
|
|
117
|
+
this.explain();
|
|
118
|
+
}
|
|
119
|
+
destroy() {
|
|
120
|
+
this.chart.destroy();
|
|
121
|
+
this.root.remove();
|
|
122
|
+
}
|
|
123
|
+
apply(patch) {
|
|
124
|
+
this.update(patch);
|
|
125
|
+
this.o.onChange?.(this.chart.options);
|
|
126
|
+
}
|
|
127
|
+
syncToggles() {
|
|
128
|
+
const c = this.chart.options;
|
|
129
|
+
this.toggles.get('trend')?.setAttribute('aria-pressed', String(!!c.trendline));
|
|
130
|
+
this.toggles.get('forecast')?.setAttribute('aria-pressed', String(!!c.forecast));
|
|
131
|
+
this.toggles.get('highlights')?.setAttribute('aria-pressed', String(!!c.highlights));
|
|
132
|
+
this.toggles.get('labels')?.setAttribute('aria-pressed', String(!!c.dataLabels));
|
|
133
|
+
const timeOnly = ['line', 'area', 'column', 'combo'].includes(c.type);
|
|
134
|
+
const f = this.toggles.get('forecast');
|
|
135
|
+
if (f) {
|
|
136
|
+
f.disabled = !timeOnly;
|
|
137
|
+
f.title = timeOnly ? 'Project the next periods' : 'Forecast is available for line, area, column and combo charts';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
button(text, title, fn) {
|
|
141
|
+
const b = document.createElement('button');
|
|
142
|
+
b.type = 'button';
|
|
143
|
+
b.className = 'agc-control agc-btn';
|
|
144
|
+
b.textContent = text;
|
|
145
|
+
b.title = title;
|
|
146
|
+
b.addEventListener('click', fn);
|
|
147
|
+
return b;
|
|
148
|
+
}
|
|
149
|
+
toggle(tool, text, fn) {
|
|
150
|
+
const b = this.button(text, text, () => {
|
|
151
|
+
const on = b.getAttribute('aria-pressed') !== 'true';
|
|
152
|
+
b.setAttribute('aria-pressed', String(on));
|
|
153
|
+
fn(on);
|
|
154
|
+
});
|
|
155
|
+
b.classList.add('agc-toggle');
|
|
156
|
+
b.setAttribute('aria-pressed', 'false');
|
|
157
|
+
this.toggles.set(tool, b);
|
|
158
|
+
return b;
|
|
159
|
+
}
|
|
160
|
+
say(text, kind) {
|
|
161
|
+
this.note.textContent = text;
|
|
162
|
+
this.note.dataset.kind = kind;
|
|
163
|
+
this.note.hidden = false;
|
|
164
|
+
}
|
|
165
|
+
explain() {
|
|
166
|
+
this.say(explainChart(this.chart.options, this.chart.options.valueFormat), 'explain');
|
|
167
|
+
}
|
|
168
|
+
bestFit() {
|
|
169
|
+
const c = this.chart.options;
|
|
170
|
+
const recs = recommendCharts(c.data, c.categoryKey, c.series.map((s) => s.key)).filter((r) => !this.o.types || this.o.types.includes(r.type));
|
|
171
|
+
const best = recs[0];
|
|
172
|
+
if (!best)
|
|
173
|
+
return this.say('No better chart type found for this data.', 'bestfit');
|
|
174
|
+
const patch = { type: best.type };
|
|
175
|
+
if (best.type === 'combo' && c.series.length > 1)
|
|
176
|
+
patch.secondaryAxis = c.series.slice(1).map((s) => s.key);
|
|
177
|
+
this.apply(patch);
|
|
178
|
+
this.say(`Best fit: ${best.label} (score ${best.score}). ${best.reason}`, 'bestfit');
|
|
179
|
+
}
|
|
180
|
+
showData(on) {
|
|
181
|
+
this.dataWrap.hidden = !on;
|
|
182
|
+
this.dataWrap.replaceChildren(...(on ? [this.chart.getDataTable()] : []));
|
|
183
|
+
const b = this.toggles.get('data');
|
|
184
|
+
if (b) {
|
|
185
|
+
b.setAttribute('aria-pressed', String(on));
|
|
186
|
+
b.textContent = on ? 'Hide data' : 'Show data';
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
fileBase() {
|
|
190
|
+
return (this.o.fileName ?? this.chart.options.title ?? 'chart').replace(/[^\w.-]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase() || 'chart';
|
|
191
|
+
}
|
|
192
|
+
exportSvg() {
|
|
193
|
+
const blob = new Blob([this.chart.toSvgString()], { type: 'image/svg+xml' });
|
|
194
|
+
void (this.o.download ?? defaultDownload)(`${this.fileBase()}.svg`, blob);
|
|
195
|
+
this.say('SVG ready.', 'export');
|
|
196
|
+
}
|
|
197
|
+
async exportPng() {
|
|
198
|
+
try {
|
|
199
|
+
const blob = await this.chart.toPngBlob(2);
|
|
200
|
+
await (this.o.download ?? defaultDownload)(`${this.fileBase()}.png`, blob);
|
|
201
|
+
this.say('PNG ready.', 'export');
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
this.say(`Couldn't create the PNG: ${err.message}. Try SVG instead.`, 'error');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
buildCustomize() {
|
|
208
|
+
const f = document.createElement('form');
|
|
209
|
+
f.className = 'agc-customize';
|
|
210
|
+
f.setAttribute('aria-label', 'Customize chart');
|
|
211
|
+
f.addEventListener('submit', (e) => e.preventDefault());
|
|
212
|
+
const c = this.chart?.options ?? this.o.chart;
|
|
213
|
+
const row = (labelText, input) => {
|
|
214
|
+
const lab = document.createElement('label');
|
|
215
|
+
lab.className = 'agc-field';
|
|
216
|
+
const span = document.createElement('span');
|
|
217
|
+
span.className = 'agc-field-label';
|
|
218
|
+
span.textContent = labelText;
|
|
219
|
+
lab.append(span, input);
|
|
220
|
+
return lab;
|
|
221
|
+
};
|
|
222
|
+
const title = document.createElement('input');
|
|
223
|
+
title.className = 'agc-control';
|
|
224
|
+
title.value = c.title ?? '';
|
|
225
|
+
title.maxLength = 80;
|
|
226
|
+
title.placeholder = 'Chart title';
|
|
227
|
+
title.addEventListener('input', () => this.apply({ title: title.value || undefined }));
|
|
228
|
+
const palette = document.createElement('select');
|
|
229
|
+
palette.className = 'agc-control';
|
|
230
|
+
for (const [k, label] of [['theme', 'Theme colours'], ['ocean', 'Ocean'], ['vivid', 'Vivid'], ['mono', 'Monochrome']]) {
|
|
231
|
+
const op = document.createElement('option');
|
|
232
|
+
op.value = k;
|
|
233
|
+
op.textContent = label;
|
|
234
|
+
palette.append(op);
|
|
235
|
+
}
|
|
236
|
+
palette.addEventListener('change', () => this.apply({ palette: PALETTES[palette.value] }));
|
|
237
|
+
const check = (text, init, fn) => {
|
|
238
|
+
const lab = document.createElement('label');
|
|
239
|
+
lab.className = 'agc-check';
|
|
240
|
+
const cb = document.createElement('input');
|
|
241
|
+
cb.type = 'checkbox';
|
|
242
|
+
cb.checked = init;
|
|
243
|
+
cb.addEventListener('change', () => fn(cb.checked));
|
|
244
|
+
lab.append(cb, document.createTextNode(` ${text}`));
|
|
245
|
+
return lab;
|
|
246
|
+
};
|
|
247
|
+
const periods = document.createElement('input');
|
|
248
|
+
periods.type = 'number';
|
|
249
|
+
periods.min = '1';
|
|
250
|
+
periods.max = '12';
|
|
251
|
+
periods.value = String(this.o.forecastPeriods ?? 3);
|
|
252
|
+
periods.className = 'agc-control agc-control-narrow';
|
|
253
|
+
periods.addEventListener('change', () => {
|
|
254
|
+
const n = Math.max(1, Math.min(12, Number(periods.value) || 3));
|
|
255
|
+
this.o.forecastPeriods = n;
|
|
256
|
+
if (this.chart.options.forecast)
|
|
257
|
+
this.apply({ forecast: n });
|
|
258
|
+
});
|
|
259
|
+
f.append(row('Title:', title), row('Colours:', palette), row('Forecast periods:', periods), check('Legend', c.legend !== false, (v) => this.apply({ legend: v })), check('Data labels', !!c.dataLabels, (v) => this.apply({ dataLabels: v })));
|
|
260
|
+
return f;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function el(tag, cls) {
|
|
264
|
+
const e = document.createElement(tag);
|
|
265
|
+
e.className = cls;
|
|
266
|
+
return e;
|
|
267
|
+
}
|
|
268
|
+
export function createChartStudio(container, opts) {
|
|
269
|
+
return new ChartStudio(container, opts);
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=studio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio.js","sourceRoot":"","sources":["../src/studio.ts"],"names":[],"mappings":"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"}
|