UNPKG

@tanstack/charts

Version:

A chart grammar for TypeScript and JavaScript. Marks consume your data directly, channels describe visual encodings, and the engine compiles them into a renderer-neutral keyed scene. TanStack's compact scales cover common numeric and categorical mappings.

115 lines (114 loc) 3.71 kB
import { channelValues, createMark, inferredKeyValues, isChartKey, visualValue } from "./mark.js"; import { materializeLayoutXYRows, projectLayoutX, projectLayoutY } from "./resolved-layout-position.js"; import { valueKey } from "./scales.js"; import { canonicalDelaunayPoints } from "./spatial-delaunay-internal.js"; import { groupRowsByChartKey } from "./spatial-group-internal.js"; import { voronoiCellPolygons } from "./spatial-voronoi-internal.js"; function voronoi(source, options) { const data = Array.isArray(source) ? source : Array.from(source); const xValues = channelValues(data, options.x, () => void 0); const yValues = channelValues(data, options.y, () => void 0); const zValues = channelValues(data, options.z, () => null); const colorValues = channelValues(data, options.color, () => null); const completeRows = materializeLayoutXYRows(data, xValues, yValues); return createMark(({ markIndex }) => { const id = options.id ?? `voronoi-${markIndex}`; const groups = data.map((_datum, index) => { const group = zValues[index]; return isChartKey(group) ? group : null; }); const keys = inferredKeyValues(data, options.key, { groups, markId: id, warningIdentity: options }); const sourceRows = completeRows.map( (row) => ({ ...row, group: groups[row.sourceIndex] ?? null, key: keys[row.sourceIndex] ?? row.sourceIndex }) ); return { id, channels: { x: { scale: "x", values: completeRows.map((row) => row.xValue) }, y: { scale: "y", values: completeRows.map((row) => row.yValue) }, color: { scale: "color", values: colorValues.filter(isChartKey) } }, render: ({ chart, scales, color: resolveColor }) => { const xScale = scales.x; const yScale = scales.y; if (!xScale || !yScale) { throw new TypeError("voronoi: x and y scales are required"); } const rows = projectLayoutY( projectLayoutX(sourceRows, xValues, xScale), yValues, yScale ); const nodes = groupRowsByChartKey(rows).flatMap( ({ rows: groupRows }) => createCellNodes( id, data, canonicalDelaunayPoints(groupRows), chart, colorValues, resolveColor, options ) ); return { nodes: [ { kind: "group", key: id, className: "ts-chart__voronoi", ariaHidden: true, children: nodes } ] }; } }; }, options.motion); } function createCellNodes(id, data, rows, chart, colorValues, resolveColor, options) { return voronoiCellPolygons(rows, chart).map(({ pointIndex, points }) => { const row = rows[pointIndex]; const datum = row.datum; const datumIndex = row.sourceIndex; const colorValue = colorValues[datumIndex]; const fallback = resolveColor(isChartKey(colorValue) ? colorValue : null); return { kind: "area", key: JSON.stringify([id, valueKey(row.group), valueKey(row.key)]), points, style: { fill: visualValue(options.fill, datum, datumIndex, data, fallback), fillOpacity: options.fillOpacity, stroke: options.stroke === void 0 ? void 0 : visualValue(options.stroke, datum, datumIndex, data, fallback), strokeOpacity: options.strokeOpacity, strokeWidth: options.strokeWidth, strokeDasharray: options.strokeDasharray, opacity: options.opacity } }; }); } export { voronoi };