import { AxisBottom, AxisLeft } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import { leftTickLabelProps } from "@visx/axis/lib/axis/AxisLeft";
import { GridColumns, GridRows } from "@visx/grid";
import { Group } from "@visx/group";
import { scaleBand, scaleLinear } from "@visx/scale";
import { Bar } from "@visx/shape";
import { Text } from "@visx/text";
import React from "react";
import { Color } from "utils/Color";
import styles from "./BarGraph.module.css";
interface BarGraphProps {
data: BarGraphData[];
/** Width of the entire graph, in pixels. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
className?: string;
/** Font size of the category axis tick labels, in pixels. Default is 16px. */
categoryTickLabelSize?: number;
/** Font size of the value axis tick labels, in pixels. Default is 16px. */
valueTickLabelSize?: number;
/** Font size of the value that appears when hovering over a bar, in pixels. */
hoverLabelSize?: number;
/** Label text for the category axis. */
categoryAxisLabel?: string;
/** Font size of the label for the cateogry axis, in pixels. */
categoryAxisLabelSize?: number;
/** Controls the distance between the category axis label and the category axis. */
categoryAxisLabelOffset?: number;
/** Label text for the value axis. */
valueAxisLabel?: string;
/** Font size of the label for the value axis, in pixels. */
valueAxisLabelSize?: number;
/** Controls the distance between the value axis label and the value axis. */
valueAxisLabelOffset?: number;
/** Minimum width of the graph. */
minWidth?: number;
/** Breakpoint width of graph where alernating labels are displayed. Only for Vertical graphs */
widthAlternatingLabel?: number;
/** Space added to the bottom of the graph to show overflowing labels. Only for Vertical graphs */
alternatingLabelSpace?: number;
/** Default position of labels in x-axis, in px. */
defaultLabelDy?: string;
/** Position of lower labels in x-axis, in px. Only for Vertical graphs */
lowerLabelDy?: string;
}
interface BarGraphData {
category: string;
value: number;
}
const DEFAULT_LABEL_SIZE = 16;
export function BarGraphHorizontal(props: BarGraphProps) {
const {
height,
margin,
data,
className,
minWidth = 500,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
hoverLabelSize,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
defaultLabelDy = "0",
} = props;
const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth
const barPadding = 0.4;
const categoryMax = height - margin.top - margin.bottom;
const valueMax = width - margin.left - margin.right;
const getCategory = (d: BarGraphData) => d.category;
const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({
range: [0, categoryMax],
domain: data.map(getCategory),
padding: barPadding,
});
const valueScale = scaleLinear({
range: [0, valueMax],
nice: true,
domain: [0, Math.max(...data.map(getValue))],
});
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
return (
);
}
export function BarGraphVertical(props: BarGraphProps) {
const {
height,
margin,
data,
className,
minWidth = 500,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
hoverLabelSize,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
widthAlternatingLabel = 600,
alternatingLabelSpace = 80,
defaultLabelDy = `0px`,
lowerLabelDy = `30px`,
} = props;
const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth
const barPadding = 0.4;
const alternatingLabel = width <= widthAlternatingLabel;
const final_margin_bottom = alternatingLabel
? margin.bottom + alternatingLabelSpace
: margin.bottom;
const categoryMax = width - margin.left - margin.right;
const valueMax = height - margin.top - final_margin_bottom;
const getCategory = (d: BarGraphData) => d.category;
const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({
range: [0, categoryMax],
domain: data.map(getCategory),
padding: barPadding,
});
const valueScale = scaleLinear({
range: [valueMax, 0],
nice: true,
domain: [0, Math.max(...data.map(getValue))],
});
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
return (
);
}