UNPKG

@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

189 lines • 7.28 kB
// A sufficiently small value. // The Number.EPSILON is not available in the target ECMA version. // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON const EPSILON = 0.0000000000001; // When x-domain is not set explicitly - guess it based on the available data. export function computeDomainX(series) { const xValues = getXValues(series); if (xValues.length === 0) { return []; } // Assuming categorical domain. // In that case, all values are to be included. if (typeof xValues[0] === 'string') { return uniq(xValues); } // For non-categorical domain find min and max bounds. return xValues.reduce(([min, max], x) => [x < min ? x : min, max < x ? x : max], [xValues[0], xValues[0]]); } // When y-domain is not set explicitly - guess it based on the available data and series. export function computeDomainY(series, scaleType) { let min = Number.POSITIVE_INFINITY; let max = Number.NEGATIVE_INFINITY; // Find the min and max for threshold series. series.forEach(s => { if (s.type === 'threshold') { min = Math.min(min, s.y); max = Math.max(max, s.y); } }); // Find the min and max for area series considering their stacking. getXValues(series).forEach((_, xIndex) => { var _a; // Maintains the prev stack level. let stackY = scaleType === 'linear' ? 0 : EPSILON; for (const s of series) { if (s.type === 'area') { stackY = stackY + (((_a = s.data[xIndex]) === null || _a === void 0 ? void 0 : _a.y) || 0); min = Math.min(min, stackY); max = Math.max(max, stackY); } } }); // If min/max is not overridden than either series or series data is empty. if (min === Number.POSITIVE_INFINITY) { return []; } // Log scales can't start from 0, so, if possible, start from 1. if (scaleType === 'log' && min === 0 && max > 1) { return [1, max]; } return [min, max]; } // For given data, series and scales, compute all points and group them as // x:y, x:series and series:x to allow constant time access to the required point or subset. export function computePlotPoints(series, xScale, yScale) { const xValues = getXValues(series); // Lookup for xy[xIndex][yIndex] const xy = []; // Lookup for xs[xIndex][seriesIndex] const xs = []; // Lookup for sx[seriesIndex][xIndex] const sx = []; // Filter out the data which is beyond the plot for whatever reason. getVisibleData(xValues, xScale).forEach(({ x, scaledX }, xIndex) => { // Maintains the prev stack level. Starting from epsilon to not break log scales. let stackY = yScale.scaleType === 'linear' ? 0 : EPSILON; // A column of series points related to the same x. const points = []; // Collect the points, leaving y-index as 0 for now. series.forEach((s, sIndex) => { var _a; if (s.type === 'threshold') { const scaledY = yScale.d3Scale(s.y) || 0; points.push({ x: x, y0: s.y, y1: s.y, scaled: { x: scaledX, y0: scaledY, y1: scaledY }, index: { x: xIndex, s: sIndex, y: 0 }, value: 0, }); } else { const value = ((_a = s.data[xIndex]) === null || _a === void 0 ? void 0 : _a.y) || 0; const y0 = stackY; const y1 = stackY + value; points.push({ x: x, y0: y0, y1: y1, scaled: { x: scaledX, y0: yScale.d3Scale(y0) || 0, y1: yScale.d3Scale(y1) || 0 }, index: { x: xIndex, s: sIndex, y: 0 }, value: value, }); stackY = y1; } }); // Sort points by y and insert the missing y-index. points .sort((p1, p2) => p1.y1 - p2.y1) .forEach((point, index) => { point.index.y = index; // Insert the points to the respective two-dimensional lookup arrays. insertIntoMatrix(xy, point.index.x, point.index.y, point); insertIntoMatrix(xs, point.index.x, point.index.s, point); insertIntoMatrix(sx, point.index.s, point.index.x, point); }); }); return { xy, xs, sx }; } // Finds the closest point in the sorted array. export function findClosest(sortedArray, target, getter) { // The method guarantees to return a point hence empty arrays are not allowed. if (sortedArray.length === 0) { throw new Error('Invariant violation: array is empty.'); } const isAscending = getter(sortedArray[0]) < getter(sortedArray[sortedArray.length - 1]); const compare = (x) => (isAscending ? getter(x) < target : getter(x) > target); const delta = (x) => Math.abs(getter(x) - target); // Use binary search to find the closest value in a sorted array. let lo = 0; let hi = sortedArray.length - 1; while (hi - lo > 1) { const mid = Math.floor((lo + hi) / 2); if (compare(sortedArray[mid])) { lo = mid; } else { hi = mid; } } return delta(sortedArray[lo]) < delta(sortedArray[hi]) ? sortedArray[lo] : sortedArray[hi]; } // Compares all x-values between series to ensure they are consistent. export function isSeriesValid(series) { var _a; const sampleXValues = getXValues(series); for (const s of series) { if (s.type === 'area') { for (let i = 0; i < Math.max(s.data.length, sampleXValues.length); i++) { if (((_a = s.data[i]) === null || _a === void 0 ? void 0 : _a.x) !== sampleXValues[i]) { return false; } } } } return true; } // Takes first area series x-values as all data x-values are to match across series. function getXValues(series) { for (const s of series) { if (s.type === 'area') { return s.data.map(({ x }) => x); } } return []; } // Returns data that is visible in the given scale. function getVisibleData(data, xScale) { const scaledOffsetX = xScale.isCategorical() ? Math.max(0, xScale.d3Scale.bandwidth() - 1) / 2 : 0; const visibleData = []; for (const x of data) { const scaledX = xScale.d3Scale(x); if (scaledX !== undefined) { visibleData.push({ x, scaledX: scaledX + scaledOffsetX }); } } return visibleData; } // Inserts given value into a two-dimensional array. function insertIntoMatrix(matrix, row, col, value) { if (!matrix[row]) { matrix[row] = []; } matrix[row][col] = value; } // Creates new array with only unique elements of the given array. function uniq(arr) { const set = new Set(); const uniqArray = []; for (const value of arr) { if (!set.has(value)) { set.add(value); uniqArray.push(value); } } return uniqArray; } //# sourceMappingURL=utils.js.map