@awsui/components-react
Version:
On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en
104 lines • 4.63 kB
JavaScript
import { isXThreshold, isYThreshold } from './utils';
/** Combine all line series into an array of scaled data points with the given scales. */
export default function makeScaledSeries(allSeries, xScale, yScale) {
const xOffset = xScale.isCategorical() ? Math.max(0, xScale.d3Scale.bandwidth() - 1) / 2 : 0;
const scaleX = (x) => (xScale.d3Scale(x) || 0) + xOffset;
const scaleY = (y) => yScale.d3Scale(y) || 0;
const allX = getAllX(allSeries);
function mergeLineSeriesPointsWithXThresholds(scaledPoints, xThresholdSeries, xThresholdSeriesColor) {
var _a, _b;
const x = scaleX(xThresholdSeries.x);
// Locate a point the x-threshold can be inserted after (if such exists).
let bisectIndex = -1;
for (let i = 0; i < scaledPoints.length - 1; i++) {
if (scaledPoints[i].x < x && x < scaledPoints[i + 1].x) {
bisectIndex = i;
break;
}
}
// Insert x-threshold point into the given series using extrapolated Y value.
// The extrapolated value is only used to render highlighted point on the chart plot.
if (bisectIndex !== -1) {
const prevY = ((_a = scaledPoints[bisectIndex].datum) === null || _a === void 0 ? void 0 : _a.y) || 0;
const nextY = ((_b = scaledPoints[bisectIndex + 1].datum) === null || _b === void 0 ? void 0 : _b.y) || 0;
const averageY = (prevY + nextY) / 2;
scaledPoints.push({
x: x,
y: scaleY(averageY),
datum: { x: xThresholdSeries.x, y: NaN },
series: scaledPoints[bisectIndex].series,
color: xThresholdSeriesColor,
});
}
}
const scaledSeriesX = allSeries.map(({ series, color }) => {
const scaledPoints = [];
// Scale and add all line series data points.
if (series.type === 'line') {
for (const datum of series.data) {
scaledPoints.push({ x: scaleX(datum.x), y: scaleY(datum.y), datum, series, color });
}
// Sort scaled points to ensure correct x-thresholds insertion.
scaledPoints.sort((s1, s2) => s1.x - s2.x);
// Merge x-thresholds into series if they don't have a shared coordinate.
for (const otherSeries of allSeries) {
if (isXThreshold(otherSeries.series)) {
mergeLineSeriesPointsWithXThresholds(scaledPoints, otherSeries.series, otherSeries.color);
}
}
}
// Y-thresholds only have Y. To make thresholds navigable they are mapped to all defined X values.
else if (isYThreshold(series)) {
for (const x of allX) {
scaledPoints.push({ x: scaleX(x), y: scaleY(series.y), datum: { x, y: series.y }, series, color });
}
// Support threshold-only setup.
if (allX.length === 0) {
scaledPoints.push({ x: NaN, y: scaleY(series.y), series, color });
}
}
// X-thresholds only have X. The y value is taken as NaN which means there is no associated point - only vertical marker.
else if (isXThreshold(series)) {
scaledPoints.push({ x: scaleX(series.x), y: NaN, datum: { x: series.x, y: NaN }, series, color });
}
// Bar series are handled separately.
return scaledPoints;
});
// Sort scaled points by x to ensure their order matches visual order in the chart to support navigation.
return flatten(scaledSeriesX).sort((s1, s2) => s1.x - s2.x);
}
/** Collect unique x values from all data series. */
function getAllX(series) {
const addDataXSet = new Set();
for (const { series: s } of series) {
switch (s.type) {
// Add all X values from data series.
case 'bar':
case 'line':
for (const d of s.data) {
addDataXSet.add(d.x);
}
break;
case 'threshold':
// X-thresholds have a single X value.
if (isXThreshold(s)) {
addDataXSet.add(s.x);
}
// Thresholds don't have X values.
break;
}
}
const allDataX = [];
addDataXSet.forEach(x => allDataX.push(x));
return allDataX;
}
function flatten(arrays) {
const merged = [];
for (const array of arrays) {
for (const item of array) {
merged.push(item);
}
}
return merged;
}
//# sourceMappingURL=make-scaled-series.js.map