Fix GroupBarGraph component
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
6ba124ee15
commit
26b7662b9e
|
@ -1,5 +1,6 @@
|
||||||
.wrapper {
|
.wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: min-content;
|
width: min-content;
|
||||||
}
|
}
|
||||||
|
@ -35,4 +36,5 @@
|
||||||
.legend {
|
.legend {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: calc(16rem / 16);
|
margin: calc(16rem / 16);
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,18 @@ interface GroupedBarGraphProps {
|
||||||
valueAxisLabelSize?: number;
|
valueAxisLabelSize?: number;
|
||||||
/** Controls the distance between the value axis label and the value axis. */
|
/** Controls the distance between the value axis label and the value axis. */
|
||||||
valueAxisLabelOffset?: number;
|
valueAxisLabelOffset?: number;
|
||||||
legendProps?: LegendProps;
|
/** Margin for each item in the legend */
|
||||||
|
itemMargin?: string;
|
||||||
|
/** 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Best format for props
|
// Best format for props
|
||||||
|
@ -66,38 +77,21 @@ interface BarGroupData {
|
||||||
[key: string]: string | number;
|
[key: string]: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LegendProps {
|
|
||||||
/** Position of the legend, relative to the graph. */
|
|
||||||
position?: "top" | "right";
|
|
||||||
/** Font size of the labels in the legend, in pixels. Default is 16px. */
|
|
||||||
itemLabelSize?: number;
|
|
||||||
/** Gap between items in the legend, in pixels. */
|
|
||||||
itemGap?: number;
|
|
||||||
/** Distance between the legend and other adjacent elements, in pixels. */
|
|
||||||
margin?: {
|
|
||||||
top?: number;
|
|
||||||
bottom?: number;
|
|
||||||
left?: number;
|
|
||||||
right?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// BAR_PADDING must be in the range [0, 1)
|
// BAR_PADDING must be in the range [0, 1)
|
||||||
const BAR_PADDING = 0.2;
|
const BAR_PADDING = 0.2;
|
||||||
const BAR_TEXT_PADDING = 12;
|
const BAR_TEXT_PADDING = 12;
|
||||||
|
|
||||||
const DEFAULT_LABEL_SIZE = 16;
|
const DEFAULT_LABEL_SIZE = 16;
|
||||||
const DEFAULT_LEGEND_GAP = 16;
|
|
||||||
|
|
||||||
export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
const {
|
const {
|
||||||
data: propsData,
|
data: propsData,
|
||||||
barColors,
|
barColors,
|
||||||
barHoverColorsMap,
|
barHoverColorsMap,
|
||||||
width,
|
|
||||||
height,
|
height,
|
||||||
margin,
|
margin,
|
||||||
className,
|
className,
|
||||||
|
minWidth = 500,
|
||||||
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
|
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
valueTickLabelSize = DEFAULT_LABEL_SIZE,
|
valueTickLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
hoverLabelSize,
|
hoverLabelSize,
|
||||||
|
@ -107,15 +101,17 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
valueAxisLabel,
|
valueAxisLabel,
|
||||||
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
|
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
valueAxisLabelOffset = 0,
|
valueAxisLabelOffset = 0,
|
||||||
legendProps,
|
itemMargin = "0 0 0 15px",
|
||||||
|
widthAlternatingLabel = 600,
|
||||||
|
alternatingLabelSpace = 80,
|
||||||
|
defaultLabelDy = `0px`,
|
||||||
|
lowerLabelDy = `30px`,
|
||||||
} = props;
|
} = props;
|
||||||
|
const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth
|
||||||
const {
|
const alternatingLabel = width <= widthAlternatingLabel;
|
||||||
position: legendPosition = "right",
|
const final_margin_bottom = alternatingLabel
|
||||||
itemLabelSize: legendLabelSize = DEFAULT_LABEL_SIZE,
|
? margin.bottom + alternatingLabelSpace
|
||||||
itemGap: legendItemGap = DEFAULT_LEGEND_GAP,
|
: margin.bottom;
|
||||||
margin: legendMargin = {},
|
|
||||||
} = legendProps ?? {};
|
|
||||||
|
|
||||||
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
|
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
|
||||||
return { category: datum.category, ...datum.values };
|
return { category: datum.category, ...datum.values };
|
||||||
|
@ -139,7 +135,7 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
const categoryMax = width - margin.left - margin.right;
|
const categoryMax = width - margin.left - margin.right;
|
||||||
const valueMax = height - margin.top - margin.bottom;
|
const valueMax = height - margin.top - final_margin_bottom;
|
||||||
|
|
||||||
const getCategory = (d: BarGroupData) => d.category;
|
const getCategory = (d: BarGroupData) => d.category;
|
||||||
|
|
||||||
|
@ -168,10 +164,15 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className ? `${className} ${styles.wrapper}` : styles.wrapper}
|
className={className ? `${className} ${styles.wrapper}` : styles.wrapper}
|
||||||
style={{
|
|
||||||
flexDirection: legendPosition === "right" ? "row" : "column-reverse",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
|
<div className={styles.legend}>
|
||||||
|
<LegendOrdinal
|
||||||
|
scale={colorScale}
|
||||||
|
direction="row"
|
||||||
|
itemMargin={itemMargin}
|
||||||
|
labelAlign="center"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<svg width={width} height={height}>
|
<svg width={width} height={height}>
|
||||||
<defs>
|
<defs>
|
||||||
{Object.keys(barHoverColorsMap).map((color: string) => {
|
{Object.keys(barHoverColorsMap).map((color: string) => {
|
||||||
|
@ -256,11 +257,13 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
left={margin.left}
|
left={margin.left}
|
||||||
hideAxisLine
|
hideAxisLine
|
||||||
hideTicks
|
hideTicks
|
||||||
tickLabelProps={() => {
|
tickLabelProps={(value, index) => {
|
||||||
|
const alternatingDy =
|
||||||
|
index % 2 == 0 ? defaultLabelDy : lowerLabelDy;
|
||||||
return {
|
return {
|
||||||
...bottomTickLabelProps(),
|
...bottomTickLabelProps(),
|
||||||
className: styles.tickLabel,
|
className: styles.tickLabel,
|
||||||
dy: "-0.25rem",
|
dy: alternatingLabel ? alternatingDy : defaultLabelDy,
|
||||||
fontSize: `${categoryTickLabelSize / 16}rem`,
|
fontSize: `${categoryTickLabelSize / 16}rem`,
|
||||||
width: categoryScale.bandwidth(),
|
width: categoryScale.bandwidth(),
|
||||||
verticalAnchor: "start",
|
verticalAnchor: "start",
|
||||||
|
@ -297,27 +300,6 @@ export function GroupedBarGraphVertical(props: GroupedBarGraphProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<LegendOrdinal
|
|
||||||
className={styles.legend}
|
|
||||||
style={{
|
|
||||||
marginTop: legendMargin.top,
|
|
||||||
marginRight: legendMargin.right,
|
|
||||||
marginBottom: legendMargin.bottom,
|
|
||||||
marginLeft: legendMargin.left,
|
|
||||||
fontSize: legendLabelSize,
|
|
||||||
}}
|
|
||||||
scale={colorScale}
|
|
||||||
direction={legendPosition === "right" ? "column" : "row"}
|
|
||||||
itemMargin={
|
|
||||||
legendPosition === "right"
|
|
||||||
? `calc(${legendItemGap / 2}rem / 16) 0 calc(${
|
|
||||||
legendItemGap / 2
|
|
||||||
}rem / 16) 0`
|
|
||||||
: `0 calc(${legendItemGap / 2}rem / 16) 0 calc(${
|
|
||||||
legendItemGap / 2
|
|
||||||
}rem / 16)`
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -327,10 +309,10 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) {
|
||||||
data: propsData,
|
data: propsData,
|
||||||
barColors,
|
barColors,
|
||||||
barHoverColorsMap,
|
barHoverColorsMap,
|
||||||
width,
|
|
||||||
height,
|
height,
|
||||||
margin,
|
margin,
|
||||||
className,
|
className,
|
||||||
|
minWidth = 600,
|
||||||
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
|
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
valueTickLabelSize = DEFAULT_LABEL_SIZE,
|
valueTickLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
hoverLabelSize,
|
hoverLabelSize,
|
||||||
|
@ -340,15 +322,10 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) {
|
||||||
valueAxisLabel,
|
valueAxisLabel,
|
||||||
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
|
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
|
||||||
valueAxisLabelOffset = 0,
|
valueAxisLabelOffset = 0,
|
||||||
legendProps,
|
itemMargin = "0 0 0 15px",
|
||||||
|
defaultLabelDy = "0",
|
||||||
} = props;
|
} = props;
|
||||||
|
const width = props.width < minWidth ? minWidth : props.width; // Ensuring graph's width >= minWidth
|
||||||
const {
|
|
||||||
position: legendPosition = "top",
|
|
||||||
itemLabelSize: legendLabelSize = DEFAULT_LABEL_SIZE,
|
|
||||||
itemGap: legendItemGap = DEFAULT_LEGEND_GAP,
|
|
||||||
margin: legendMargin = {},
|
|
||||||
} = legendProps ?? {};
|
|
||||||
|
|
||||||
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
|
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
|
||||||
return { category: datum.category, ...datum.values };
|
return { category: datum.category, ...datum.values };
|
||||||
|
@ -401,10 +378,15 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className ? `${className} ${styles.wrapper}` : styles.wrapper}
|
className={className ? `${className} ${styles.wrapper}` : styles.wrapper}
|
||||||
style={{
|
|
||||||
flexDirection: legendPosition === "right" ? "row" : "column-reverse",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
|
<div className={styles.legend}>
|
||||||
|
<LegendOrdinal
|
||||||
|
scale={colorScale}
|
||||||
|
direction="row"
|
||||||
|
itemMargin={itemMargin}
|
||||||
|
labelAlign="center"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<svg width={width} height={height}>
|
<svg width={width} height={height}>
|
||||||
<defs>
|
<defs>
|
||||||
{Object.keys(barHoverColorsMap).map((color: string) => {
|
{Object.keys(barHoverColorsMap).map((color: string) => {
|
||||||
|
@ -495,7 +477,7 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) {
|
||||||
...leftTickLabelProps(),
|
...leftTickLabelProps(),
|
||||||
className: styles.tickLabel,
|
className: styles.tickLabel,
|
||||||
dx: "-0.5rem",
|
dx: "-0.5rem",
|
||||||
dy: "0.25rem",
|
dy: defaultLabelDy,
|
||||||
fontSize: `${valueTickLabelSize / 16}rem`,
|
fontSize: `${valueTickLabelSize / 16}rem`,
|
||||||
height: categoryScale.bandwidth(),
|
height: categoryScale.bandwidth(),
|
||||||
};
|
};
|
||||||
|
@ -531,27 +513,6 @@ export function GroupedBarGraphHorizontal(props: GroupedBarGraphProps) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<LegendOrdinal
|
|
||||||
className={styles.legend}
|
|
||||||
style={{
|
|
||||||
marginTop: legendMargin.top,
|
|
||||||
marginRight: legendMargin.right,
|
|
||||||
marginBottom: legendMargin.bottom,
|
|
||||||
marginLeft: legendMargin.left,
|
|
||||||
fontSize: legendLabelSize,
|
|
||||||
}}
|
|
||||||
scale={colorScale}
|
|
||||||
direction={legendPosition === "right" ? "column" : "row"}
|
|
||||||
itemMargin={
|
|
||||||
legendPosition === "right"
|
|
||||||
? `calc(${legendItemGap / 2}rem / 16) 0 calc(${
|
|
||||||
legendItemGap / 2
|
|
||||||
}rem / 16) 0`
|
|
||||||
: `0 calc(${legendItemGap / 2}rem / 16) 0 calc(${
|
|
||||||
legendItemGap / 2
|
|
||||||
}rem / 16)`
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue