UNPKG

recharts

Version:
177 lines (175 loc) 7.08 kB
import { MAX_VALUE_REG, MIN_VALUE_REG } from './ChartUtils'; import { isNumber } from './DataUtils'; import { isWellBehavedNumber } from './isWellBehavedNumber'; export function isWellFormedNumberDomain(v) { if (Array.isArray(v) && v.length === 2) { var [min, max] = v; if (isWellBehavedNumber(min) && isWellBehavedNumber(max)) { return true; } } return false; } export function extendDomain(providedDomain, boundaryDomain, allowDataOverflow) { if (allowDataOverflow) { // If the data are allowed to overflow - we're fine with whatever user provided return providedDomain; } /* * If the data are not allowed to overflow - we need to extend the domain. * Means that effectively the user is allowed to make the domain larger * but not smaller. */ return [Math.min(providedDomain[0], boundaryDomain[0]), Math.max(providedDomain[1], boundaryDomain[1])]; } /** * So Recharts allows users to provide their own domains, * but it also places some expectations on what the domain is. * We can improve on the typescript typing, but we also need a runtime test to observe that the user-provided domain is well-formed, * that is: an array with exactly two numbers. * * This function does not accept data as an argument. * This is to enable a performance optimization - if the domain is there, * and we know what it is without traversing all the data, * then we don't have to traverse all the data! * * If the user-provided domain is not well-formed, * this function will return undefined - in which case we should traverse the data to calculate the real domain. * * This function is for parsing the numerical domain only. * * @param userDomain external prop, user provided, before validation. Can have various shapes: array, function, special magical strings inside too. * @param allowDataOverflow boolean, provided by users. If true then the data domain wins * * @return [min, max] domain if it's well-formed; undefined if the domain is invalid */ export function numericalDomainSpecifiedWithoutRequiringData(userDomain, allowDataOverflow) { if (!allowDataOverflow) { // Cannot compute data overflow if the data is not provided return undefined; } if (typeof userDomain === 'function') { // The user function expects the data to be provided as an argument return undefined; } if (Array.isArray(userDomain) && userDomain.length === 2) { var [providedMin, providedMax] = userDomain; var finalMin, finalMax; if (isWellBehavedNumber(providedMin)) { finalMin = providedMin; } else if (typeof providedMin === 'function') { // The user function expects the data to be provided as an argument return undefined; } if (isWellBehavedNumber(providedMax)) { finalMax = providedMax; } else if (typeof providedMax === 'function') { // The user function expects the data to be provided as an argument return undefined; } var candidate = [finalMin, finalMax]; if (isWellFormedNumberDomain(candidate)) { return candidate; } } return undefined; } /** * So Recharts allows users to provide their own domains, * but it also places some expectations on what the domain is. * We can improve on the typescript typing, but we also need a runtime test * to observe that the user-provided domain is well-formed, * that is: an array with exactly two numbers. * If the user-provided domain is not well-formed, * this function will return undefined - in which case we should traverse the data to calculate the real domain. * * This function is for parsing the numerical domain only. * * You are probably thinking, why does domain need tick count? * Well it adjusts the domain based on where the "nice ticks" land, and nice ticks depend on the tick count. * * @param userDomain external prop, user provided, before validation. Can have various shapes: array, function, special magical strings inside too. * @param dataDomain calculated from data. Can be undefined, as an option for performance optimization * @param allowDataOverflow provided by users. If true then the data domain wins * * @return [min, max] domain if it's well-formed; undefined if the domain is invalid */ export function parseNumericalUserDomain(userDomain, dataDomain, allowDataOverflow) { if (!allowDataOverflow && dataDomain == null) { // Cannot compute data overflow if the data is not provided return undefined; } if (typeof userDomain === 'function' && dataDomain != null) { try { var result = userDomain(dataDomain, allowDataOverflow); if (isWellFormedNumberDomain(result)) { return extendDomain(result, dataDomain, allowDataOverflow); } } catch (_unused) { /* ignore the exception and compute domain from data later */ } } if (Array.isArray(userDomain) && userDomain.length === 2) { var [providedMin, providedMax] = userDomain; var finalMin, finalMax; if (providedMin === 'auto') { if (dataDomain != null) { finalMin = Math.min(...dataDomain); } } else if (isNumber(providedMin)) { finalMin = providedMin; } else if (typeof providedMin === 'function') { try { if (dataDomain != null) { finalMin = providedMin(dataDomain === null || dataDomain === void 0 ? void 0 : dataDomain[0]); } } catch (_unused2) { /* ignore the exception and compute domain from data later */ } } else if (typeof providedMin === 'string' && MIN_VALUE_REG.test(providedMin)) { var match = MIN_VALUE_REG.exec(providedMin); if (match == null || dataDomain == null) { finalMin = undefined; } else { var value = +match[1]; finalMin = dataDomain[0] - value; } } else { finalMin = dataDomain === null || dataDomain === void 0 ? void 0 : dataDomain[0]; } if (providedMax === 'auto') { if (dataDomain != null) { finalMax = Math.max(...dataDomain); } } else if (isNumber(providedMax)) { finalMax = providedMax; } else if (typeof providedMax === 'function') { try { if (dataDomain != null) { finalMax = providedMax(dataDomain === null || dataDomain === void 0 ? void 0 : dataDomain[1]); } } catch (_unused3) { /* ignore the exception and compute domain from data later */ } } else if (typeof providedMax === 'string' && MAX_VALUE_REG.test(providedMax)) { var _match = MAX_VALUE_REG.exec(providedMax); if (_match == null || dataDomain == null) { finalMax = undefined; } else { var _value = +_match[1]; finalMax = dataDomain[1] + _value; } } else { finalMax = dataDomain === null || dataDomain === void 0 ? void 0 : dataDomain[1]; } var candidate = [finalMin, finalMax]; if (isWellFormedNumberDomain(candidate)) { if (dataDomain == null) { return candidate; } return extendDomain(candidate, dataDomain, allowDataOverflow); } } return undefined; }