react-plot
Version:
Library of React components to render SVG 2D plots.
138 lines • 4.42 kB
JavaScript
import { useMemo } from 'react';
let currentValue = 1;
/**
* Creates autoincremental values, generally for series.
*/
export function getNextId() {
return ++currentValue;
}
export function useId(id, prefix) {
return useMemo(() => {
if (id)
return id;
return `${prefix}-${getNextId()}`;
}, [id, prefix]);
}
const horizontal = ['top', 'bottom'];
const vertical = ['left', 'right'];
/**
* Validates that two positions are not orthogonal between them
*/
export function validatePosition(currPosition, position, id) {
const error = (horizontal.includes(currPosition) && !horizontal.includes(position)) ||
(vertical.includes(currPosition) && !vertical.includes(position));
if (error) {
throw new Error(`The positions are ortogonal for ${id}`);
}
}
/**
* Validates that two axes are orthogonal between them
*/
export function validateAxis(axisContext, xKey, yKey, options = {}) {
const { onlyOrthogonal = false } = options;
const xAxis = axisContext[xKey];
const yAxis = axisContext[yKey];
if (!xAxis || !yAxis)
return [undefined, undefined];
if (onlyOrthogonal &&
((horizontal.includes(xAxis.position) &&
horizontal.includes(yAxis.position)) ||
(vertical.includes(yAxis.position) && vertical.includes(xAxis.position)))) {
throw new Error(`The axis ${xKey} and ${yKey} are not orthogonal`);
}
if (!onlyOrthogonal &&
(horizontal.includes(xAxis.position)
? !vertical.includes(yAxis.position)
: vertical.includes(xAxis.position))) {
if (vertical.includes(xAxis.position) ||
horizontal.includes(yAxis.position)) {
throw new Error(`The axis ${xKey} should be ${horizontal.join(' ')} and ${yKey} should be ${vertical.join(' ')}`);
}
throw new Error(`The axis ${xKey} and ${yKey} are not orthogonal`);
}
return [xAxis.scale, yAxis.scale];
}
/**
* Checks the style added to a component and if is a function, gets the resulting value
*/
export function functionalStyle(defaultStyle, elementStyle, point, index, data) {
const style = { ...defaultStyle };
for (const key in elementStyle) {
// @ts-expect-error Type is too complex
if (typeof elementStyle[key] === 'function') {
// @ts-expect-error Type is too complex
style[key] = elementStyle[key](point, index, data);
}
else {
// @ts-expect-error Type is too complex
style[key] = elementStyle[key];
}
}
return style;
}
/**
* Checks the marker added to a component and if is a function, gets the resulting value
*/
export function functionalShape(elementStyle, point, index, data) {
let shape;
if (typeof elementStyle === 'function') {
shape = elementStyle(point, index, data);
}
else {
shape = elementStyle;
}
return shape;
}
/**
* Checks the label added to a component and if is a function, gets the resulting value
*/
export function functionalLabel(elementStyle, point, index, data) {
let shape;
if (typeof elementStyle === 'function') {
shape = elementStyle(point, index, data);
}
else {
shape = elementStyle;
}
return shape;
}
/**
* validate series point Error
*/
export function validateSeriesPointError(error) {
if (typeof error === 'number')
return [error, error];
else if (Array.isArray(error) && error.length >= 2)
return error;
return null;
}
export function closestPoint(data, value, distanceFun) {
const closest = {
index: 0,
distance: Number.POSITIVE_INFINITY,
};
for (let i = 0; i < data.length; i++) {
const distance = distanceFun(data[i], value);
if (distance < closest.distance) {
closest.index = i;
closest.distance = distance;
}
}
return data[closest.index];
}
export function dataConvertDate(data) {
return data.map(({ x, y }) => ({ x: toNumber(x), y: toNumber(y) }));
}
export function toNumber(value) {
if (value === undefined) {
return value;
}
if (typeof value === 'number') {
return value;
}
return value.getTime();
}
export function middlePoint(point1, point2) {
return { x: (point1.x + point2.x) / 2, y: (point1.y + point2.y) / 2 };
}
//# sourceMappingURL=utils.js.map