UNPKG

react-native-chart-kit

Version:

Beautiful React Native charts for dashboards, reports, and data-rich mobile apps.

110 lines (109 loc) 3.77 kB
const finiteValues = (values) => { return values.filter((value) => Number.isFinite(value)); }; const expandDegenerateDomain = ([min, max]) => { if (min !== max) { return [min, max]; } if (min === 0) { return [-1, 1]; } const padding = Math.abs(min) * 0.5; return [min - padding, max + padding]; }; const resolveNumericDomainValue = (value, dataMin, dataMax, fallback) => { if (value === "dataMin") { return dataMin; } if (value === "dataMax") { return dataMax; } return typeof value === "number" && Number.isFinite(value) ? value : fallback; }; export const resolveNumericDomain = (values, input = "auto") => { const finite = finiteValues(values); const dataMin = finite.length > 0 ? Math.min(...finite) : 0; const dataMax = finite.length > 0 ? Math.max(...finite) : 0; if (input === "auto") { return expandDegenerateDomain([dataMin, dataMax]); } if (Array.isArray(input)) { return expandDegenerateDomain([ resolveNumericDomainValue(input[0], dataMin, dataMax, dataMin), resolveNumericDomainValue(input[1], dataMin, dataMax, dataMax) ]); } let min = resolveNumericDomainValue(input.min, dataMin, dataMax, dataMin); let max = resolveNumericDomainValue(input.max, dataMin, dataMax, dataMax); if (input.includeZero) { min = Math.min(min, 0); max = Math.max(max, 0); } const domain = expandDegenerateDomain([min, max]); return input.nice ? niceNumericDomain(domain) : domain; }; const resolveTimeInput = (value, dataMin, dataMax, fallback) => { if (value === "dataMin") { return dataMin; } if (value === "dataMax") { return dataMax; } if (value === undefined) { return fallback; } const date = value instanceof Date ? value : new Date(value); return Number.isFinite(date.valueOf()) ? date : fallback; }; export const resolveTimeDomain = (values, input = "auto") => { const validTimes = values .map((value) => value.valueOf()) .filter((value) => Number.isFinite(value)); const dataMin = new Date(validTimes.length > 0 ? Math.min(...validTimes) : 0); const dataMax = new Date(validTimes.length > 0 ? Math.max(...validTimes) : 0); let domain; if (input === "auto") { domain = [dataMin, dataMax]; } else if (Array.isArray(input)) { domain = [ resolveTimeInput(input[0], dataMin, dataMax, dataMin), resolveTimeInput(input[1], dataMin, dataMax, dataMax) ]; } else { domain = [ resolveTimeInput(input.min, dataMin, dataMax, dataMin), resolveTimeInput(input.max, dataMin, dataMax, dataMax) ]; } if (domain[0].valueOf() === domain[1].valueOf()) { const center = domain[0].valueOf(); return [new Date(center - 1), new Date(center + 1)]; } return domain; }; export const tickStep = (start, stop, count) => { const rawStep = Math.abs(stop - start) / Math.max(0, count); if (!Number.isFinite(rawStep) || rawStep === 0) { return 0; } const power = Math.floor(Math.log10(rawStep)); const error = rawStep / Math.pow(10, power); const factor = error >= Math.sqrt(50) ? 10 : error >= Math.sqrt(10) ? 5 : error >= Math.sqrt(2) ? 2 : 1; return factor * Math.pow(10, power); }; export const niceNumericDomain = (domain, count = 5) => { const [min, max] = domain; const step = tickStep(min, max, count); if (step === 0) { return expandDegenerateDomain(domain); } return [Math.floor(min / step) * step, Math.ceil(max / step) * step]; };