import { useMemo } from 'react'; import { __, always, append, curry, divide, identity, ifElse, pipe, prepend, prop, reduce, reverse, subtract, } from 'ramda'; import { scaleLinear } from 'd3-scale'; import { GaugeProps } from 'types'; import { mapIndexed } from 'utils'; const angleScale = scaleLinear() .domain([0, 1]) .range([-Math.PI / 2, Math.PI / 2]) .clamp(true); const calculateEvenPortion = curry((_: unknown, i: number[], arr: unknown[]) => // @ts-ignore pipe(prop('length'), subtract(__, 1), divide(i))(arr) ); const checkInverse = (inverse: boolean) => ifElse(always(inverse), reverse, identity); const getDomain = ( min: number, max: number, inverse: boolean, segmentEnds: number[] ) => pipe(prepend(min), append(max), checkInverse(inverse))(segmentEnds); const getRange = (inverse: boolean, domain: number[]) => // @ts-ignore pipe(mapIndexed(calculateEvenPortion), checkInverse(inverse))(domain); const getPercentScale = ( min: number, max: number, inverse: boolean, segmentEnds: number[] ) => { const domain = getDomain(min, max, inverse, segmentEnds); return scaleLinear().domain(domain).range(getRange(inverse, domain)); }; const dataReducer = ( acc: { colors: string[]; labels: string[] }, cur: { color: string; label: string } ) => ({ colors: [...acc.colors, cur.color], labels: [...acc.labels, cur.label], }); const parseData = reduce(dataReducer, { colors: [], labels: [] }); export const useComponentLogic = ({ data, hideArrow, inverse, max, min, segmentEnds, value, }: GaugeProps) => { const percentScale = getPercentScale(min, max, inverse, segmentEnds); const percent = percentScale(value); const angle = angleScale(percent); const { colors, labels: inputLabels } = useMemo( () => parseData(data), [data] ); const labels: string[] = useMemo( () => ifElse(always(inverse), reverse, identity)(inputLabels), [inverse, inputLabels] ); return { angle, colors, hideArrow, labels, value }; };