@unovis/mcp 1.7.0-mcp.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 +193 -0
- package/README.md +154 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +109 -0
- package/dist/cli.js.map +1 -0
- package/dist/codegen/index.d.ts +14 -0
- package/dist/codegen/index.js +346 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/env/bbox.d.ts +13 -0
- package/dist/env/bbox.js +335 -0
- package/dist/env/bbox.js.map +1 -0
- package/dist/env/canvas.d.ts +9 -0
- package/dist/env/canvas.js +55 -0
- package/dist/env/canvas.js.map +1 -0
- package/dist/env/computed-style.d.ts +38 -0
- package/dist/env/computed-style.js +186 -0
- package/dist/env/computed-style.js.map +1 -0
- package/dist/env/fonts.d.ts +3 -0
- package/dist/env/fonts.js +103 -0
- package/dist/env/fonts.js.map +1 -0
- package/dist/env/index.d.ts +13 -0
- package/dist/env/index.js +121 -0
- package/dist/env/index.js.map +1 -0
- package/dist/env/raf-queue.d.ts +23 -0
- package/dist/env/raf-queue.js +51 -0
- package/dist/env/raf-queue.js.map +1 -0
- package/dist/env/size.d.ts +9 -0
- package/dist/env/size.js +30 -0
- package/dist/env/size.js.map +1 -0
- package/dist/html/document.d.ts +16 -0
- package/dist/html/document.js +95 -0
- package/dist/html/document.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/recipes/area.d.ts +66 -0
- package/dist/recipes/area.js +76 -0
- package/dist/recipes/area.js.map +1 -0
- package/dist/recipes/bar.d.ts +67 -0
- package/dist/recipes/bar.js +69 -0
- package/dist/recipes/bar.js.map +1 -0
- package/dist/recipes/boxplot.d.ts +64 -0
- package/dist/recipes/boxplot.js +89 -0
- package/dist/recipes/boxplot.js.map +1 -0
- package/dist/recipes/chord.d.ts +41 -0
- package/dist/recipes/chord.js +72 -0
- package/dist/recipes/chord.js.map +1 -0
- package/dist/recipes/choropleth-regions.d.ts +49 -0
- package/dist/recipes/choropleth-regions.js +521 -0
- package/dist/recipes/choropleth-regions.js.map +1 -0
- package/dist/recipes/choropleth.d.ts +27 -0
- package/dist/recipes/choropleth.js +86 -0
- package/dist/recipes/choropleth.js.map +1 -0
- package/dist/recipes/donut.d.ts +25 -0
- package/dist/recipes/donut.js +51 -0
- package/dist/recipes/donut.js.map +1 -0
- package/dist/recipes/graph.d.ts +55 -0
- package/dist/recipes/graph.js +132 -0
- package/dist/recipes/graph.js.map +1 -0
- package/dist/recipes/heatmap.d.ts +21 -0
- package/dist/recipes/heatmap.js +79 -0
- package/dist/recipes/heatmap.js.map +1 -0
- package/dist/recipes/index.d.ts +5 -0
- package/dist/recipes/index.js +35 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/line.d.ts +69 -0
- package/dist/recipes/line.js +64 -0
- package/dist/recipes/line.js.map +1 -0
- package/dist/recipes/nested-donut.d.ts +22 -0
- package/dist/recipes/nested-donut.js +47 -0
- package/dist/recipes/nested-donut.js.map +1 -0
- package/dist/recipes/radial-bar.d.ts +25 -0
- package/dist/recipes/radial-bar.js +53 -0
- package/dist/recipes/radial-bar.js.map +1 -0
- package/dist/recipes/sankey.d.ts +41 -0
- package/dist/recipes/sankey.js +61 -0
- package/dist/recipes/sankey.js.map +1 -0
- package/dist/recipes/scatter.d.ts +68 -0
- package/dist/recipes/scatter.js +75 -0
- package/dist/recipes/scatter.js.map +1 -0
- package/dist/recipes/shared.d.ts +144 -0
- package/dist/recipes/shared.js +212 -0
- package/dist/recipes/shared.js.map +1 -0
- package/dist/recipes/timeline.d.ts +31 -0
- package/dist/recipes/timeline.js +123 -0
- package/dist/recipes/timeline.js.map +1 -0
- package/dist/recipes/treemap.d.ts +19 -0
- package/dist/recipes/treemap.js +43 -0
- package/dist/recipes/treemap.js.map +1 -0
- package/dist/recipes/types.d.ts +16 -0
- package/dist/recipes/types.js +2 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/render/headless.d.ts +62 -0
- package/dist/render/headless.js +158 -0
- package/dist/render/headless.js.map +1 -0
- package/dist/render/materialize.d.ts +35 -0
- package/dist/render/materialize.js +160 -0
- package/dist/render/materialize.js.map +1 -0
- package/dist/render/mutex.d.ts +9 -0
- package/dist/render/mutex.js +14 -0
- package/dist/render/mutex.js.map +1 -0
- package/dist/render/rasterize.d.ts +10 -0
- package/dist/render/rasterize.js +29 -0
- package/dist/render/rasterize.js.map +1 -0
- package/dist/render/renderer.d.ts +21 -0
- package/dist/render/renderer.js +66 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/spec.d.ts +95 -0
- package/dist/render/spec.js +15 -0
- package/dist/render/spec.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +44 -0
- package/dist/server.js.map +1 -0
- package/dist/svg/collect-css.d.ts +14 -0
- package/dist/svg/collect-css.js +53 -0
- package/dist/svg/collect-css.js.map +1 -0
- package/dist/svg/css-vars.d.ts +17 -0
- package/dist/svg/css-vars.js +64 -0
- package/dist/svg/css-vars.js.map +1 -0
- package/dist/svg/header.d.ts +8 -0
- package/dist/svg/header.js +81 -0
- package/dist/svg/header.js.map +1 -0
- package/dist/svg/ids.d.ts +12 -0
- package/dist/svg/ids.js +94 -0
- package/dist/svg/ids.js.map +1 -0
- package/dist/svg/postprocess.d.ts +41 -0
- package/dist/svg/postprocess.js +135 -0
- package/dist/svg/postprocess.js.map +1 -0
- package/dist/tools/register.d.ts +12 -0
- package/dist/tools/register.js +127 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/widget/bundle.js +1777 -0
- package/dist/widget/bundle.meta.json +3 -0
- package/dist/widget/entry.d.ts +34 -0
- package/dist/widget/entry.js +118 -0
- package/dist/widget/entry.js.map +1 -0
- package/dist/widget/interactions.d.ts +14 -0
- package/dist/widget/interactions.js +151 -0
- package/dist/widget/interactions.js.map +1 -0
- package/dist/widget/unovis-slim.d.ts +33 -0
- package/dist/widget/unovis-slim.js +34 -0
- package/dist/widget/unovis-slim.js.map +1 -0
- package/docs/README.md +56 -0
- package/docs/architecture.md +158 -0
- package/docs/chart-spec.md +148 -0
- package/docs/getting-started.md +175 -0
- package/docs/interactive.md +125 -0
- package/docs/output-types.md +170 -0
- package/docs/programmatic.md +234 -0
- package/docs/tools.md +273 -0
- package/docs/troubleshooting.md +140 -0
- package/fonts/README.md +19 -0
- package/package.json +73 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/** Shared schema fragments and helpers for chart recipes.
|
|
2
|
+
*
|
|
3
|
+
* Conventions:
|
|
4
|
+
* - data is always an array of flat records
|
|
5
|
+
* - accessors are field names (never code)
|
|
6
|
+
* - every option has a description and a sane default
|
|
7
|
+
* - enums over free-form strings, bounded numbers
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { ChartInputError } from '../render/materialize.js';
|
|
11
|
+
export { ChartInputError };
|
|
12
|
+
// ── schema fragments ────────────────────────────────────────────────────────
|
|
13
|
+
export const dataValue = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
14
|
+
export const dataRecords = z.array(z.record(z.string(), dataValue)).min(1)
|
|
15
|
+
.describe('Chart data: an array of flat records, e.g. [{"month": "Jan", "sales": 120, "cost": 80}, ...]');
|
|
16
|
+
export const fieldName = z.string().min(1);
|
|
17
|
+
export const commonInput = {
|
|
18
|
+
width: z.number().int().min(100).max(4000).default(800).describe('Chart width in pixels'),
|
|
19
|
+
height: z.number().int().min(100).max(4000).default(480).describe('Chart height in pixels'),
|
|
20
|
+
theme: z.enum(['light', 'dark']).default('light').describe('Color theme of the chart'),
|
|
21
|
+
title: z.string().optional().describe('Chart title rendered above the chart'),
|
|
22
|
+
colors: z.array(z.string().regex(/^#[0-9a-fA-F]{3,8}$/, 'hex color, e.g. #4D8CFD')).max(12).optional()
|
|
23
|
+
.describe('Custom color palette (hex). Replaces the default palette in order'),
|
|
24
|
+
framework: z.enum(['ts', 'react', 'svelte', 'vue', 'angular', 'solid']).default('ts')
|
|
25
|
+
.describe('Target framework for outputType "code". ts emits the imperative @unovis/ts API'),
|
|
26
|
+
outputType: z.enum(['svg', 'png', 'html', 'interactive', 'config', 'code']).default('svg')
|
|
27
|
+
.describe('svg: SVG markup; png: a rendered PNG image; html: a self-contained interactive HTML file ' +
|
|
28
|
+
'(tooltips, crosshair, hover — saved to disk, path returned); interactive: an interactive chart ' +
|
|
29
|
+
'rendered inline by clients that support MCP UI widgets; config: the resolved Unovis chart spec as JSON'),
|
|
30
|
+
outputPath: z.string().optional()
|
|
31
|
+
.describe('Absolute file path with an extension matching outputType (.svg, .png or .html) — saves the chart to disk and returns the path instead of inline content'),
|
|
32
|
+
scale: z.number().min(1).max(4).default(2)
|
|
33
|
+
.describe('Pixel density multiplier for PNG output (2 = retina). Ignored for svg/config'),
|
|
34
|
+
};
|
|
35
|
+
export const xyInput = {
|
|
36
|
+
xAxisLabel: z.string().optional().describe('Label for the X axis'),
|
|
37
|
+
yAxisLabel: z.string().optional().describe('Label for the Y axis'),
|
|
38
|
+
showGridLines: z.boolean().default(true).describe('Show horizontal/vertical grid lines'),
|
|
39
|
+
legend: z.boolean().default(true).describe('Show a legend (multi-series charts only)'),
|
|
40
|
+
};
|
|
41
|
+
const hexColor = z.string().regex(/^#[0-9a-fA-F]{3,8}$/, 'hex color, e.g. #FF6B7E');
|
|
42
|
+
/** Reference-line / shaded-band decorations available on XY charts */
|
|
43
|
+
export const xyDecorations = {
|
|
44
|
+
referenceLines: z.array(z.object({
|
|
45
|
+
axis: z.enum(['x', 'y']).default('y').describe('y: horizontal line at a Y value; x: vertical line at an X value'),
|
|
46
|
+
value: z.number().describe('Position in data units'),
|
|
47
|
+
label: z.string().optional().describe('Small label next to the line'),
|
|
48
|
+
color: hexColor.optional(),
|
|
49
|
+
lineWidth: z.number().min(0.5).max(10).default(1.5),
|
|
50
|
+
style: z.enum(['dashed', 'solid', 'dotted']).default('dashed'),
|
|
51
|
+
})).max(8).optional().describe('Reference lines for thresholds/targets, e.g. an SLA or goal'),
|
|
52
|
+
referenceBands: z.array(z.object({
|
|
53
|
+
axis: z.enum(['x', 'y']).default('y'),
|
|
54
|
+
from: z.number().describe('Band start, in data units'),
|
|
55
|
+
to: z.number().describe('Band end, in data units'),
|
|
56
|
+
label: z.string().optional(),
|
|
57
|
+
color: hexColor.optional(),
|
|
58
|
+
})).max(8).optional().describe('Shaded ranges drawn behind the data, e.g. an acceptable range'),
|
|
59
|
+
};
|
|
60
|
+
/** Decoration components: bands render behind the data, lines on top */
|
|
61
|
+
export function decorationComponents(input) {
|
|
62
|
+
const bands = (input.referenceBands ?? []).map(band => ({
|
|
63
|
+
type: 'Plotband',
|
|
64
|
+
config: {
|
|
65
|
+
axis: band.axis,
|
|
66
|
+
from: band.from,
|
|
67
|
+
to: band.to,
|
|
68
|
+
...(band.color ? { color: band.color } : {}),
|
|
69
|
+
...(band.label ? { labelText: band.label } : {}),
|
|
70
|
+
},
|
|
71
|
+
}));
|
|
72
|
+
const lines = (input.referenceLines ?? []).map(line => ({
|
|
73
|
+
type: 'Plotline',
|
|
74
|
+
config: {
|
|
75
|
+
axis: line.axis,
|
|
76
|
+
value: line.value,
|
|
77
|
+
lineWidth: line.lineWidth,
|
|
78
|
+
lineStyle: line.style,
|
|
79
|
+
...(line.color ? { color: line.color } : {}),
|
|
80
|
+
...(line.label ? { labelText: line.label } : {}),
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
return { bands, lines };
|
|
84
|
+
}
|
|
85
|
+
export const field = (name, as) => ({ $field: name, as });
|
|
86
|
+
export const toArray = (value) => (Array.isArray(value) ? value : [value]);
|
|
87
|
+
/** Throw an actionable error when referenced fields are missing from the data */
|
|
88
|
+
export function assertFieldsExist(data, fields) {
|
|
89
|
+
const first = data[0];
|
|
90
|
+
if (!first || typeof first !== 'object')
|
|
91
|
+
throw new ChartInputError('data must be an array of objects');
|
|
92
|
+
const available = Object.keys(first);
|
|
93
|
+
const missing = fields.filter((f) => !!f && !(f in first));
|
|
94
|
+
if (missing.length) {
|
|
95
|
+
throw new ChartInputError(`Field${missing.length > 1 ? 's' : ''} ${missing.map(f => `"${f}"`).join(', ')} not found in data. ` +
|
|
96
|
+
`Available fields: ${available.map(f => `"${f}"`).join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** True when every value of a field (in the first few records) is numeric */
|
|
100
|
+
export function isNumericField(data, fieldName) {
|
|
101
|
+
const sample = data.slice(0, 20);
|
|
102
|
+
return sample.every(d => d[fieldName] === null || d[fieldName] === undefined || typeof d[fieldName] === 'number' ||
|
|
103
|
+
(typeof d[fieldName] === 'string' && d[fieldName] !== '' && !Number.isNaN(Number(d[fieldName]))));
|
|
104
|
+
}
|
|
105
|
+
/** Distinct values of a field, in first-seen order */
|
|
106
|
+
export function distinctValues(data, fieldName) {
|
|
107
|
+
const seen = new Set();
|
|
108
|
+
for (const record of data) {
|
|
109
|
+
const value = record[fieldName];
|
|
110
|
+
if (value === null || value === undefined)
|
|
111
|
+
continue;
|
|
112
|
+
seen.add(value);
|
|
113
|
+
}
|
|
114
|
+
return Array.from(seen);
|
|
115
|
+
}
|
|
116
|
+
/** Numeric fields map directly; string categories map to their index with
|
|
117
|
+
* labeled ticks (Unovis XY scales are numeric). */
|
|
118
|
+
export function categoricalX(data, fieldName, isTime) {
|
|
119
|
+
if (isTime)
|
|
120
|
+
return { x: field(fieldName, 'date') };
|
|
121
|
+
if (isNumericField(data, fieldName))
|
|
122
|
+
return { x: field(fieldName, 'number') };
|
|
123
|
+
const categories = distinctValues(data, fieldName).map(String);
|
|
124
|
+
return { x: { $index: true }, categories };
|
|
125
|
+
}
|
|
126
|
+
/** Axis spec for a categorical dimension: one labeled tick per category.
|
|
127
|
+
* Explicit integer tickValues — approximate d3 tick counts can emit
|
|
128
|
+
* fractional ticks that would round into duplicate category labels. */
|
|
129
|
+
export function categoryAxis(base, categories) {
|
|
130
|
+
const maxTicks = 30;
|
|
131
|
+
const step = Math.ceil(categories.length / maxTicks);
|
|
132
|
+
const tickValues = categories.map((_, i) => i).filter(i => i % step === 0);
|
|
133
|
+
return {
|
|
134
|
+
...base,
|
|
135
|
+
tickFormat: { $lookup: categories },
|
|
136
|
+
tickValues,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const MINUTE = 60_000;
|
|
140
|
+
const HOUR = 60 * MINUTE;
|
|
141
|
+
const DAY = 24 * HOUR;
|
|
142
|
+
/** Calendar-aligned tick values for date axes. Linear-scale ticks land at
|
|
143
|
+
* arbitrary times of day, which the date formatter would render as
|
|
144
|
+
* time-of-day labels ("08:53 AM" on a 3-month chart) — align ticks to
|
|
145
|
+
* month/day/hour/minute boundaries instead. */
|
|
146
|
+
export function dateTickValues(min, max, target = 7) {
|
|
147
|
+
const span = max - min;
|
|
148
|
+
if (!Number.isFinite(span) || span <= 0)
|
|
149
|
+
return undefined;
|
|
150
|
+
const ticks = [];
|
|
151
|
+
if (span >= 60 * DAY) { // month starts
|
|
152
|
+
const stepMonths = Math.max(1, Math.ceil(span / (30 * DAY) / target));
|
|
153
|
+
const start = new Date(min);
|
|
154
|
+
let date = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), 1));
|
|
155
|
+
if (date.getTime() < min)
|
|
156
|
+
date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 1));
|
|
157
|
+
while (date.getTime() <= max && ticks.length < 24) {
|
|
158
|
+
ticks.push(date.getTime());
|
|
159
|
+
date = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + stepMonths, 1));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// day / hour / minute boundaries (uniform in UTC epoch time)
|
|
164
|
+
const unit = span >= 2 * DAY ? DAY : span >= 2 * HOUR ? HOUR : MINUTE;
|
|
165
|
+
const niceSteps = unit === DAY ? [1, 2, 7, 14] : unit === HOUR ? [1, 2, 3, 6, 12] : [1, 2, 5, 10, 15, 30];
|
|
166
|
+
const rawStep = span / unit / target;
|
|
167
|
+
const step = (niceSteps.find(s => s >= rawStep) ?? Math.ceil(rawStep)) * unit;
|
|
168
|
+
for (let t = Math.ceil(min / step) * step; t <= max && ticks.length < 24; t += step)
|
|
169
|
+
ticks.push(t);
|
|
170
|
+
}
|
|
171
|
+
return ticks.length >= 2 ? ticks : undefined;
|
|
172
|
+
}
|
|
173
|
+
/** Tick values for a time axis derived from the data extent of a date field */
|
|
174
|
+
export function timeTickValuesFromData(data, fieldName) {
|
|
175
|
+
let min = Infinity;
|
|
176
|
+
let max = -Infinity;
|
|
177
|
+
for (const record of data) {
|
|
178
|
+
const raw = record[fieldName];
|
|
179
|
+
if (raw === null || raw === undefined || raw === '')
|
|
180
|
+
continue;
|
|
181
|
+
const time = typeof raw === 'number' ? raw : new Date(String(raw)).getTime();
|
|
182
|
+
if (Number.isNaN(time))
|
|
183
|
+
continue;
|
|
184
|
+
if (time < min)
|
|
185
|
+
min = time;
|
|
186
|
+
if (time > max)
|
|
187
|
+
max = time;
|
|
188
|
+
}
|
|
189
|
+
return dateTickValues(min, max);
|
|
190
|
+
}
|
|
191
|
+
export function seriesLegend(labels, enabled, colors) {
|
|
192
|
+
if (!enabled || labels.length < 2)
|
|
193
|
+
return undefined;
|
|
194
|
+
return labels.map((name, i) => ({ name, paletteIndex: i, color: colors?.[i % (colors.length || 1)] }));
|
|
195
|
+
}
|
|
196
|
+
/** Common ChartSpec fields from common tool inputs */
|
|
197
|
+
export function baseSpec(input) {
|
|
198
|
+
return {
|
|
199
|
+
width: input.width,
|
|
200
|
+
height: input.height,
|
|
201
|
+
theme: input.theme,
|
|
202
|
+
title: input.title,
|
|
203
|
+
colors: input.colors,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export function xyAxes(input) {
|
|
207
|
+
return {
|
|
208
|
+
xAxis: { label: input.xAxisLabel, gridLine: input.showGridLines },
|
|
209
|
+
yAxis: { label: input.yAxisLabel, gridLine: input.showGridLines },
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/recipes/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Recipe } from './types.js';
|
|
3
|
+
/** Calendar-aligned axis tick values (UTC) for a time extent. Linear-scale
|
|
4
|
+
* ticks land on decimal-nice epoch values (mid-day times), which format as
|
|
5
|
+
* times of day and lose the date — so we pick month/day/hour boundaries
|
|
6
|
+
* instead. Returns undefined for degenerate extents. */
|
|
7
|
+
export declare const timelineInputShape: {
|
|
8
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
9
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
10
|
+
theme: z.ZodDefault<z.ZodEnum<["light", "dark"]>>;
|
|
11
|
+
title: z.ZodOptional<z.ZodString>;
|
|
12
|
+
colors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
13
|
+
framework: z.ZodDefault<z.ZodEnum<["ts", "react", "svelte", "vue", "angular", "solid"]>>;
|
|
14
|
+
outputType: z.ZodDefault<z.ZodEnum<["svg", "png", "html", "interactive", "config", "code"]>>;
|
|
15
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
16
|
+
scale: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>, "many">;
|
|
18
|
+
row: z.ZodString;
|
|
19
|
+
start: z.ZodString;
|
|
20
|
+
end: z.ZodOptional<z.ZodString>;
|
|
21
|
+
duration: z.ZodOptional<z.ZodString>;
|
|
22
|
+
timeIsDate: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
showRowLabels: z.ZodDefault<z.ZodBoolean>;
|
|
24
|
+
rowHeight: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
lineWidth: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
roundedEnds: z.ZodDefault<z.ZodBoolean>;
|
|
27
|
+
alternatingRowColors: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
xAxisLabel: z.ZodOptional<z.ZodString>;
|
|
29
|
+
showGridLines: z.ZodDefault<z.ZodBoolean>;
|
|
30
|
+
};
|
|
31
|
+
export declare const timelineRecipe: Recipe<typeof timelineInputShape>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { commonInput, xyInput, dataRecords, fieldName, assertFieldsExist, baseSpec, dateTickValues, field, isNumericField, ChartInputError, } from './shared.js';
|
|
3
|
+
/** Coerce a raw record value to a time position: numbers pass through,
|
|
4
|
+
* strings are parsed as dates (→ epoch milliseconds) */
|
|
5
|
+
const toTime = (value) => {
|
|
6
|
+
if (typeof value === 'number')
|
|
7
|
+
return value;
|
|
8
|
+
if (typeof value === 'string' && value !== '') {
|
|
9
|
+
const numeric = Number(value);
|
|
10
|
+
if (!Number.isNaN(numeric))
|
|
11
|
+
return numeric;
|
|
12
|
+
const time = new Date(value).getTime();
|
|
13
|
+
if (!Number.isNaN(time))
|
|
14
|
+
return time;
|
|
15
|
+
}
|
|
16
|
+
return NaN;
|
|
17
|
+
};
|
|
18
|
+
/** Calendar-aligned axis tick values (UTC) for a time extent. Linear-scale
|
|
19
|
+
* ticks land on decimal-nice epoch values (mid-day times), which format as
|
|
20
|
+
* times of day and lose the date — so we pick month/day/hour boundaries
|
|
21
|
+
* instead. Returns undefined for degenerate extents. */
|
|
22
|
+
export const timelineInputShape = {
|
|
23
|
+
data: dataRecords,
|
|
24
|
+
row: fieldName.describe('Field with the row (lane) name. Records sharing a row value are drawn in one lane'),
|
|
25
|
+
start: fieldName.describe('Field with the item start: a number, or a date string (e.g. "2024-03-01")'),
|
|
26
|
+
end: fieldName.optional()
|
|
27
|
+
.describe('Field with the item end, same format as start. Provide either end or duration'),
|
|
28
|
+
duration: fieldName.optional()
|
|
29
|
+
.describe('Field with the item duration, in the same units as start (milliseconds when start is a date). Ignored when end is provided'),
|
|
30
|
+
timeIsDate: z.boolean().optional()
|
|
31
|
+
.describe('Treat start/end values as dates (time axis). Auto-detected from the start field when omitted'),
|
|
32
|
+
showRowLabels: z.boolean().default(true).describe('Show the row names on the left'),
|
|
33
|
+
rowHeight: z.number().min(10).max(100).default(22).describe('Row height in pixels'),
|
|
34
|
+
lineWidth: z.number().min(1).max(60).optional()
|
|
35
|
+
.describe('Thickness of the timeline bars in pixels. Defaults to a value derived from rowHeight'),
|
|
36
|
+
roundedEnds: z.boolean().default(false).describe('Draw the bars with rounded ends'),
|
|
37
|
+
alternatingRowColors: z.boolean().default(true).describe('Alternate the row background colors'),
|
|
38
|
+
xAxisLabel: xyInput.xAxisLabel,
|
|
39
|
+
showGridLines: xyInput.showGridLines,
|
|
40
|
+
...commonInput,
|
|
41
|
+
};
|
|
42
|
+
export const timelineRecipe = {
|
|
43
|
+
name: 'generate_timeline_chart',
|
|
44
|
+
title: 'Timeline chart',
|
|
45
|
+
description: 'Generate a timeline (Gantt-style) chart of items with a start and an end (or duration), grouped into labeled rows. ' +
|
|
46
|
+
'Use for schedules, project plans, traces, or event durations. Provide either an end field or a duration field. ' +
|
|
47
|
+
'Example: data=[{"task":"Design","from":"2024-01-08","to":"2024-02-02"},...], row="task", start="from", end="to".',
|
|
48
|
+
inputShape: timelineInputShape,
|
|
49
|
+
toSpec: (input) => {
|
|
50
|
+
const data = input.data;
|
|
51
|
+
if (!input.end && !input.duration) {
|
|
52
|
+
throw new ChartInputError('Either "end" or "duration" must be provided');
|
|
53
|
+
}
|
|
54
|
+
assertFieldsExist(data, [input.row, input.start, input.end, input.duration]);
|
|
55
|
+
const isDate = input.timeIsDate ?? !isNumericField(data, input.start);
|
|
56
|
+
// Normalize into flat numeric positions: start (epoch ms for dates) and
|
|
57
|
+
// duration (end - start when an end field is given). A synthetic id keeps
|
|
58
|
+
// items distinct even when a row has two items starting at the same time.
|
|
59
|
+
const normalized = data.map((d, i) => {
|
|
60
|
+
const start = isDate ? toTime(d[input.start]) : Number(d[input.start]);
|
|
61
|
+
if (!Number.isFinite(start)) {
|
|
62
|
+
throw new ChartInputError(`Invalid "${input.start}" value in record ${i}: ${JSON.stringify(d[input.start])}`);
|
|
63
|
+
}
|
|
64
|
+
let duration;
|
|
65
|
+
if (input.end) {
|
|
66
|
+
const end = isDate ? toTime(d[input.end]) : Number(d[input.end]);
|
|
67
|
+
if (!Number.isFinite(end)) {
|
|
68
|
+
throw new ChartInputError(`Invalid "${input.end}" value in record ${i}: ${JSON.stringify(d[input.end])}`);
|
|
69
|
+
}
|
|
70
|
+
duration = end - start;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
duration = Number(d[input.duration]);
|
|
74
|
+
}
|
|
75
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
76
|
+
throw new ChartInputError(`Record ${i} has an invalid or negative duration: ${JSON.stringify(duration)}`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
...d,
|
|
80
|
+
_id: `item-${i}`,
|
|
81
|
+
_row: d[input.row] === null || d[input.row] === undefined ? 'Unknown' : String(d[input.row]),
|
|
82
|
+
_start: start,
|
|
83
|
+
_duration: duration,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
// Calendar-aligned ticks for date axes: default linear ticks land on
|
|
87
|
+
// decimal-nice epoch values, which format as times of day.
|
|
88
|
+
let tickValues;
|
|
89
|
+
if (isDate) {
|
|
90
|
+
const min = Math.min(...normalized.map(d => d._start));
|
|
91
|
+
const max = Math.max(...normalized.map(d => d._start + d._duration));
|
|
92
|
+
tickValues = dateTickValues(min, max);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
container: 'xy',
|
|
96
|
+
...baseSpec(input),
|
|
97
|
+
components: [{
|
|
98
|
+
type: 'Timeline',
|
|
99
|
+
config: {
|
|
100
|
+
id: { $field: '_id' },
|
|
101
|
+
x: field('_start', 'number'),
|
|
102
|
+
lineRow: { $field: '_row' },
|
|
103
|
+
lineDuration: field('_duration', 'number'),
|
|
104
|
+
showRowLabels: input.showRowLabels,
|
|
105
|
+
rowMaxLabelWidth: Math.max(120, Math.round(input.width * 0.2)),
|
|
106
|
+
rowHeight: input.rowHeight,
|
|
107
|
+
...(input.lineWidth !== undefined ? { lineWidth: input.lineWidth } : {}),
|
|
108
|
+
lineCap: input.roundedEnds,
|
|
109
|
+
showEmptySegments: true,
|
|
110
|
+
alternatingRowColors: input.alternatingRowColors,
|
|
111
|
+
},
|
|
112
|
+
}],
|
|
113
|
+
xAxis: {
|
|
114
|
+
label: input.xAxisLabel,
|
|
115
|
+
gridLine: input.showGridLines,
|
|
116
|
+
tickFormat: isDate ? { $dateTickFormat: true } : { $numTickFormat: true },
|
|
117
|
+
...(tickValues ? { tickValues } : {}),
|
|
118
|
+
},
|
|
119
|
+
data: normalized,
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/recipes/timeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Recipe } from './types.js';
|
|
3
|
+
export declare const treemapInputShape: {
|
|
4
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
theme: z.ZodDefault<z.ZodEnum<["light", "dark"]>>;
|
|
7
|
+
title: z.ZodOptional<z.ZodString>;
|
|
8
|
+
colors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
framework: z.ZodDefault<z.ZodEnum<["ts", "react", "svelte", "vue", "angular", "solid"]>>;
|
|
10
|
+
outputType: z.ZodDefault<z.ZodEnum<["svg", "png", "html", "interactive", "config", "code"]>>;
|
|
11
|
+
outputPath: z.ZodOptional<z.ZodString>;
|
|
12
|
+
scale: z.ZodDefault<z.ZodNumber>;
|
|
13
|
+
data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>, "many">;
|
|
14
|
+
layers: z.ZodArray<z.ZodString, "many">;
|
|
15
|
+
value: z.ZodString;
|
|
16
|
+
labelInternalNodes: z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
tilePadding: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
};
|
|
19
|
+
export declare const treemapRecipe: Recipe<typeof treemapInputShape>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { commonInput, dataRecords, fieldName, assertFieldsExist, baseSpec, field } from './shared.js';
|
|
3
|
+
export const treemapInputShape = {
|
|
4
|
+
data: dataRecords,
|
|
5
|
+
layers: z.array(fieldName).min(1).max(4)
|
|
6
|
+
.describe('Fields defining the hierarchy, top-level groups first, e.g. ["sector", "company"]'),
|
|
7
|
+
value: fieldName.describe('Field with the numeric tile size'),
|
|
8
|
+
labelInternalNodes: z.boolean().optional()
|
|
9
|
+
.describe('Show labels on the group (non-leaf) tiles. Defaults to true when there is more than one layer'),
|
|
10
|
+
tilePadding: z.number().min(0).max(24).default(2).describe('Padding between tiles in pixels'),
|
|
11
|
+
...commonInput,
|
|
12
|
+
};
|
|
13
|
+
export const treemapRecipe = {
|
|
14
|
+
name: 'generate_treemap',
|
|
15
|
+
title: 'Treemap',
|
|
16
|
+
description: 'Generate a treemap of nested rectangles sized by value. Use for part-of-whole comparisons, ' +
|
|
17
|
+
'optionally across hierarchy levels. Tiles are labeled "name: value". ' +
|
|
18
|
+
'Example: data=[{"sector":"Tech","company":"Apple","cap":2900},{"sector":"Energy","company":"Shell","cap":210}], layers=["sector","company"], value="cap".',
|
|
19
|
+
inputShape: treemapInputShape,
|
|
20
|
+
toSpec: (input) => {
|
|
21
|
+
const data = input.data;
|
|
22
|
+
assertFieldsExist(data, [...input.layers, input.value]);
|
|
23
|
+
const labelInternalNodes = input.labelInternalNodes ?? input.layers.length > 1;
|
|
24
|
+
return {
|
|
25
|
+
container: 'single',
|
|
26
|
+
...baseSpec(input),
|
|
27
|
+
components: [{
|
|
28
|
+
type: 'Treemap',
|
|
29
|
+
config: {
|
|
30
|
+
layers: input.layers.map(layer => field(layer)),
|
|
31
|
+
value: field(input.value, 'number'),
|
|
32
|
+
labelInternalNodes,
|
|
33
|
+
tilePadding: input.tilePadding,
|
|
34
|
+
// Group labels render inside the group tile — reserve headroom for them
|
|
35
|
+
...(labelInternalNodes ? { tilePaddingTop: 22 } : {}),
|
|
36
|
+
tileShowHtmlTooltip: false,
|
|
37
|
+
},
|
|
38
|
+
}],
|
|
39
|
+
data,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=treemap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treemap.js","sourceRoot":"","sources":["../../src/recipes/treemap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGrG,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SACrC,QAAQ,CAAC,mFAAmF,CAAC;IAChG,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAC7D,kBAAkB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SACvC,QAAQ,CAAC,+FAA+F,CAAC;IAC5G,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC7F,GAAG,WAAW;CACf,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAqC;IAC7D,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,6FAA6F;QACxG,uEAAuE;QACvE,2JAA2J;IAC7J,UAAU,EAAE,iBAAiB;IAC7B,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAChB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAoB,CAAA;QACvC,iBAAiB,CAAC,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;QAEvD,MAAM,kBAAkB,GAAG,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;QAE9E,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,GAAG,QAAQ,CAAC,KAAK,CAAC;YAClB,UAAU,EAAE,CAAC;oBACX,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE;wBACN,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;wBAC/C,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC;wBACnC,kBAAkB;wBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;wBAC9B,wEAAwE;wBACxE,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACrD,mBAAmB,EAAE,KAAK;qBAC3B;iBACF,CAAC;YACF,IAAI;SACL,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ZodRawShape, ZodObject, infer as ZodInfer } from 'zod';
|
|
2
|
+
import type { ChartSpec } from '../render/spec.js';
|
|
3
|
+
/** A recipe maps a simplified, LLM-friendly tool input onto a ChartSpec.
|
|
4
|
+
* `toSpec` must be pure and produce a JSON-serializable spec — it doubles
|
|
5
|
+
* as the `config` output mode and, later, as input for code generation. */
|
|
6
|
+
export interface Recipe<Shape extends ZodRawShape = ZodRawShape> {
|
|
7
|
+
/** MCP tool name, e.g. 'generate_line_chart' */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Human-readable title, e.g. 'Line chart' */
|
|
10
|
+
title: string;
|
|
11
|
+
/** LLM-facing tool description — say when to use it and show a data example */
|
|
12
|
+
description: string;
|
|
13
|
+
inputShape: Shape;
|
|
14
|
+
toSpec(input: ZodInfer<ZodObject<Shape>>): ChartSpec;
|
|
15
|
+
}
|
|
16
|
+
export type AnyRecipe = Recipe<any>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/recipes/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { UnovisLib } from '../env/index.js';
|
|
2
|
+
import type { SvgFrame } from '../svg/postprocess.js';
|
|
3
|
+
export interface HeadlessRenderOptions extends SvgFrame {
|
|
4
|
+
/** Deterministic id prefix (snapshot tests); random per render otherwise */
|
|
5
|
+
idPrefix?: string;
|
|
6
|
+
/** Keep emotion classes and skip style inlining (debug) */
|
|
7
|
+
keepClasses?: boolean;
|
|
8
|
+
/** Frame drawn around the chart so content never touches the image edge.
|
|
9
|
+
* The chart renders at width/height minus this padding. */
|
|
10
|
+
padding?: {
|
|
11
|
+
top: number;
|
|
12
|
+
right: number;
|
|
13
|
+
bottom: number;
|
|
14
|
+
left: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Handed to the build callback. */
|
|
18
|
+
export interface BuildContext {
|
|
19
|
+
/** Sized host element to render the chart into */
|
|
20
|
+
container: HTMLElement;
|
|
21
|
+
/** The shim-initialised @unovis/ts namespace — use this, don't import it */
|
|
22
|
+
unovis: UnovisLib;
|
|
23
|
+
/** Inner chart size (options size minus padding) */
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
/** Pass as the container config's `onRenderComplete` */
|
|
27
|
+
onRenderComplete: () => void;
|
|
28
|
+
/** Pass as the `onRenderComplete` of components whose layout is async
|
|
29
|
+
* (Graph), after calling `requireComponentReady()` */
|
|
30
|
+
onComponentReady: () => void;
|
|
31
|
+
/** Declare that a component signals readiness separately, so the render
|
|
32
|
+
* waits for `onComponentReady` as well */
|
|
33
|
+
requireComponentReady: () => void;
|
|
34
|
+
}
|
|
35
|
+
export interface RenderResult {
|
|
36
|
+
svg: string;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
warnings: string[];
|
|
40
|
+
}
|
|
41
|
+
/** A chart instance, as returned by any Unovis container */
|
|
42
|
+
export interface RenderedChart {
|
|
43
|
+
element?: Element | null;
|
|
44
|
+
destroy?: () => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Render a chart to standalone SVG in Node.
|
|
48
|
+
*
|
|
49
|
+
* ```ts
|
|
50
|
+
* const { svg } = await renderToSvg({ width: 800, height: 400 }, (ctx) => {
|
|
51
|
+
* const line = new ctx.unovis.Line({ x: d => d.x, y: d => d.y, duration: 0 })
|
|
52
|
+
* return new ctx.unovis.XYContainer(ctx.container, {
|
|
53
|
+
* components: [line],
|
|
54
|
+
* width: ctx.width,
|
|
55
|
+
* height: ctx.height,
|
|
56
|
+
* duration: 0,
|
|
57
|
+
* onRenderComplete: ctx.onRenderComplete,
|
|
58
|
+
* }, data)
|
|
59
|
+
* })
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function renderToSvg(options: HeadlessRenderOptions, build: (context: BuildContext) => RenderedChart): Promise<RenderResult>;
|