cl-react-graph
Version:
React D3 Charts
104 lines (96 loc) • 2.69 kB
text/typescript
import { extent } from "d3-array";
//useDomain is a React hook to calculate a chart domain, used in Axis and Bars
import { useMemo } from "react";
/*
* Depending on the axis group layout we need to take the values and work out what the
* y axis domain bounds need to be.
* */
import { BarChartDataSet, EGroupedBarLayout } from "../Histogram";
import { LineChartDataSet } from "../LineChart";
import { ScatterPlotDataSet } from "../ScatterPlot";
type LineProps = {
values: LineChartDataSet<any>[];
clampToZero?: boolean;
};
type ScatterProps = {
values: ScatterPlotDataSet<any>[];
clampToZero?: boolean;
};
type Props = {
groupLayout: EGroupedBarLayout;
bins: string[];
values: BarChartDataSet[];
clampToZero?: boolean;
/**
* Axis tick values - these could have a greater extend than the chart data so should
* be included in the domain calculation
*/
tickValues: number[];
};
// Y Domains only so far....
export const useHistogramDomain: (props: Props) => [number, number] = ({
groupLayout,
bins,
values,
tickValues,
clampToZero = true,
}) => {
return useMemo(() => {
let allValues: number[] = [];
allValues =
groupLayout === EGroupedBarLayout.STACKED
? bins.map((bin, binIndex) =>
values
.map((dataset) => dataset.data[binIndex])
.reduce((p, n) => p + n, 0),
)
: values.reduce(
(prev, dataset) => prev.concat(dataset.data),
[] as number[],
);
if (clampToZero) {
allValues.push(0);
}
const e = extent(allValues.concat(tickValues)) as [number, number];
if (e[0] === e[1]) {
e[1]++;
}
return e;
}, [bins, groupLayout, values, tickValues, clampToZero]);
};
export const useLineDomain: (props: LineProps) => [number, number] = ({
values,
clampToZero,
}) => {
return useMemo(() => {
const allValues = values.reduce((prev, value) => {
return prev.concat(value.data.map((d) => d.y));
}, [] as number[]);
if (clampToZero) {
allValues.push(0);
}
const e = extent(allValues) as [number, number];
if (e[0] === e[1]) {
e[1]++;
}
return e;
}, [values, clampToZero]);
};
export const useScatterDomain: (props: ScatterProps) => [number, number] = ({
values,
clampToZero,
}) => {
return useMemo(() => {
const allValues = values.reduce((prev, value) => {
return prev.concat(value.data.map((d) => d.y));
}, [] as number[]);
if (clampToZero) {
allValues.push(0);
}
const e = extent(allValues) as [number, number];
if (e[0] === e[1]) {
e[1]++;
}
return e;
}, [values, clampToZero]);
};