@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/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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"}
@@ -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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"}