@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.
67 lines (66 loc) • 2.46 kB
JavaScript
import { valueKey } from "./scales.js";
const focusGroupX = axisFocus("x", true);
const focusGroupY = axisFocus("y", true);
const focusNearestX = axisFocus("x", false);
const focusNearestY = axisFocus("y", false);
function axisFocus(axis, grouped) {
const coordinate = (point) => axis === "x" ? point.x : point.y;
const value = (point) => axis === "x" ? point.xValue : point.yValue;
const secondary = (point) => axis === "x" ? point.y : point.x;
return {
resolve(points, context) {
const { x, y, maxDistance } = context;
const target = axis === "x" ? x : y;
let nearest;
let distance = maxDistance;
for (const point of points) {
const nextDistance = Math.abs(coordinate(point) - target);
if (nextDistance >= distance) continue;
nearest = point;
distance = nextDistance;
}
if (!nearest) return [];
const candidates = groupPoints(points, nearest, value);
const secondaryTarget = axis === "x" ? y : x;
const primary = candidates.reduce(
(closest, candidate) => Math.abs(secondary(candidate) - secondaryTarget) < Math.abs(secondary(closest) - secondaryTarget) ? candidate : closest,
nearest
);
return grouped ? [primary, ...candidates.filter((point) => point !== primary)] : [primary];
},
group(points, context) {
const { point } = context;
return grouped ? groupPoints(points, point, value) : [point];
},
navigation(points) {
const sorted = [...points].sort(
(left, right) => left.x - right.x || left.y - right.y
);
if (!grouped) return sorted;
const unique = /* @__PURE__ */ new Map();
for (const point of sorted) {
const key = valueKey(value(point));
if (!unique.has(key)) unique.set(key, point);
}
return [...unique.values()];
}
};
}
function groupPoints(points, point, value) {
const key = valueKey(value(point));
const unique = /* @__PURE__ */ new Map();
unique.set(valueKey(point.group), point);
for (const candidate of points) {
if (valueKey(value(candidate)) !== key) continue;
const group = valueKey(candidate.group);
if (!unique.has(group)) unique.set(group, candidate);
}
const sorted = [...unique.values()].sort((left, right) => left.y - right.y);
return [point, ...sorted.filter((candidate) => candidate !== point)];
}
export {
focusGroupX,
focusGroupY,
focusNearestX,
focusNearestY
};