@patternfly/react-charts
Version:
This library provides a set of React chart components for use with the PatternFly reference implementation.
215 lines • 14.1 kB
JavaScript
import * as React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import { VictoryChart } from 'victory-chart';
import { getComparativeMeasureErrorWidth, getComparativeMeasureWidth, getComparativeMeasureWarningWidth, getPrimaryDotMeasureSize, getPrimarySegmentedMeasureWidth, getQualitativeRangeBarWidth } from './utils/chart-bullet-size';
import { getBulletDomain } from './utils/chart-bullet-domain';
import { getBulletThemeWithLegendColorScale } from './utils/chart-bullet-theme';
import { ChartAxis } from '../ChartAxis';
import { ChartBulletComparativeErrorMeasure } from './ChartBulletComparativeErrorMeasure';
import { ChartBulletComparativeMeasure } from './ChartBulletComparativeMeasure';
import { ChartBulletComparativeWarningMeasure } from './ChartBulletComparativeWarningMeasure';
import { ChartBulletGroupTitle } from './ChartBulletGroupTitle';
import { ChartBulletPrimaryDotMeasure } from './ChartBulletPrimaryDotMeasure';
import { ChartBulletPrimarySegmentedMeasure } from './ChartBulletPrimarySegmentedMeasure';
import { ChartBulletQualitativeRange } from './ChartBulletQualitativeRange';
import { ChartBulletTitle } from './ChartBulletTitle';
import { ChartContainer } from '../ChartContainer';
import { ChartLegend, ChartLegendPosition } from '../ChartLegend';
import { ChartBulletStyles } from '../ChartTheme';
import { ChartTooltip } from '../ChartTooltip';
import { getComputedLegend, getPaddingForSide } from '../ChartUtils';
export const ChartBullet = ({ allowTooltip = true, ariaDesc, ariaTitle, axisComponent = React.createElement(ChartAxis, null), comparativeErrorMeasureComponent = React.createElement(ChartBulletComparativeErrorMeasure, null), comparativeErrorMeasureData, comparativeErrorMeasureDataY, comparativeErrorMeasureLegendData, comparativeWarningMeasureComponent = React.createElement(ChartBulletComparativeWarningMeasure, null), comparativeWarningMeasureData, comparativeWarningMeasureDataY, comparativeWarningMeasureLegendData, comparativeZeroMeasureComponent = React.createElement(ChartBulletComparativeMeasure, null), constrainToVisibleArea = false, groupTitleComponent = React.createElement(ChartBulletGroupTitle, null), groupSubTitle, groupTitle, horizontal = true, invert = false, labels, legendAllowWrap = false, legendComponent = React.createElement(ChartLegend, null), legendItemsPerRow, legendPosition = 'bottom', maxDomain, minDomain, name, padding, primaryDotMeasureComponent = React.createElement(ChartBulletPrimaryDotMeasure, null), primaryDotMeasureData, primaryDotMeasureDataY, primaryDotMeasureLegendData, primarySegmentedMeasureComponent = React.createElement(ChartBulletPrimarySegmentedMeasure, null), primarySegmentedMeasureData, primarySegmentedMeasureDataY, primarySegmentedMeasureLegendData, qualitativeRangeComponent = React.createElement(ChartBulletQualitativeRange, null), qualitativeRangeData, qualitativeRangeDataY, qualitativeRangeDataY0, qualitativeRangeLegendData, standalone = true, subTitle, themeColor,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
themeVariant, title, titleComponent = React.createElement(ChartBulletTitle, null), titlePosition,
// destructure last
theme = getBulletThemeWithLegendColorScale({
comparativeErrorMeasureData,
comparativeErrorMeasureLegendData,
comparativeWarningMeasureData,
comparativeWarningMeasureLegendData,
invert,
primaryDotMeasureData,
primaryDotMeasureLegendData,
primarySegmentedMeasureData,
primarySegmentedMeasureLegendData,
qualitativeRangeData,
qualitativeRangeLegendData,
themeColor
}), domain = getBulletDomain({
comparativeErrorMeasureComponent,
comparativeErrorMeasureData,
comparativeWarningMeasureComponent,
comparativeWarningMeasureData,
maxDomain,
minDomain,
primaryDotMeasureComponent,
primaryDotMeasureData,
primarySegmentedMeasureComponent,
primarySegmentedMeasureData,
qualitativeRangeComponent,
qualitativeRangeData
}), legendOrientation = theme.legend.orientation, height = horizontal ? theme.chart.height : theme.chart.width, width = horizontal ? theme.chart.width : theme.chart.height, bulletSize = theme.chart.height }) => {
// Note that we're using a fixed bullet height width to align components.
const chartSize = {
height: horizontal ? bulletSize : height,
width: horizontal ? width : bulletSize
};
const defaultPadding = {
bottom: getPaddingForSide('bottom', padding, theme.chart.padding),
left: getPaddingForSide('left', padding, theme.chart.padding),
right: getPaddingForSide('right', padding, theme.chart.padding),
top: getPaddingForSide('top', padding, theme.chart.padding)
};
// Bullet group title
const bulletGroupTitle = React.cloneElement(groupTitleComponent, Object.assign(Object.assign(Object.assign({ height }, (name && { name: `${name}-${groupTitleComponent.type.displayName}` })), { standalone: false, subTitle: groupSubTitle, title: groupTitle, width }), groupTitleComponent.props));
// Bullet title
const bulletTitle = React.cloneElement(titleComponent, Object.assign(Object.assign(Object.assign({ height,
horizontal,
legendPosition }, (name && { name: `${name}-${titleComponent.type.displayName}` })), { padding, standalone: false, subTitle,
theme,
title,
titlePosition,
width }), titleComponent.props));
// Comparative error measure
const comparativeErrorMeasure = React.cloneElement(comparativeErrorMeasureComponent, Object.assign({ allowTooltip, barWidth: getComparativeMeasureErrorWidth({ height: chartSize.height, horizontal, width: chartSize.width }), constrainToVisibleArea, data: comparativeErrorMeasureData, domain, height: chartSize.height, horizontal, labelComponent: allowTooltip ? React.createElement(ChartTooltip, { height: height, theme: theme, width: width }) : undefined, labels,
padding, standalone: false, width: chartSize.width, y: comparativeErrorMeasureDataY }, comparativeErrorMeasureComponent.props));
// Comparative warning measure
const comparativeWarningMeasure = React.cloneElement(comparativeWarningMeasureComponent, Object.assign({ allowTooltip, barWidth: getComparativeMeasureWarningWidth({ height: chartSize.height, horizontal, width: chartSize.width }), constrainToVisibleArea, data: comparativeWarningMeasureData, domain, height: chartSize.height, horizontal, labelComponent: allowTooltip ? React.createElement(ChartTooltip, { height: height, theme: theme, width: width }) : undefined, labels,
padding, standalone: false, width: chartSize.width, y: comparativeWarningMeasureDataY }, comparativeWarningMeasureComponent.props));
// Comparative zero measure
const comparativeZeroMeasure = React.cloneElement(comparativeZeroMeasureComponent, Object.assign({ barWidth: getComparativeMeasureWidth({ height: chartSize.height, horizontal, width: chartSize.width }), data: [{ y: 0 }], domain, height: chartSize.height, horizontal,
padding, standalone: false, width: chartSize.width }, comparativeZeroMeasureComponent.props));
// Legend
const legend = React.cloneElement(legendComponent, Object.assign(Object.assign(Object.assign({ data: [
...(primaryDotMeasureLegendData ? primaryDotMeasureLegendData : []),
...(primarySegmentedMeasureLegendData ? primarySegmentedMeasureLegendData : []),
...(comparativeWarningMeasureLegendData ? comparativeWarningMeasureLegendData : []),
...(comparativeErrorMeasureLegendData ? comparativeErrorMeasureLegendData : []),
...(qualitativeRangeLegendData ? qualitativeRangeLegendData : [])
] }, (name && { name: `${name}-${legendComponent.type.displayName}` })), { itemsPerRow: legendItemsPerRow, orientation: legendOrientation, position: legendPosition, theme }), legendComponent.props));
// Primary dot measure
const primaryDotMeasure = React.cloneElement(primaryDotMeasureComponent, Object.assign({ allowTooltip,
constrainToVisibleArea, data: primaryDotMeasureData, domain, height: chartSize.height, horizontal,
invert, labelComponent: allowTooltip ? React.createElement(ChartTooltip, { height: height, theme: theme, width: width }) : undefined, labels,
padding, size: getPrimaryDotMeasureSize({ height: chartSize.height, horizontal, width: chartSize.width }), standalone: false, themeColor, width: chartSize.width, y: primaryDotMeasureDataY }, primaryDotMeasureComponent.props));
// Primary segmented measure
const primarySegmentedMeasure = React.cloneElement(primarySegmentedMeasureComponent, Object.assign({ allowTooltip,
constrainToVisibleArea, barWidth: getPrimarySegmentedMeasureWidth({ height: chartSize.height, horizontal, width: chartSize.width }), data: primarySegmentedMeasureData, domain, height: chartSize.height, horizontal,
invert, labelComponent: allowTooltip ? React.createElement(ChartTooltip, { height: height, theme: theme, width: width }) : undefined, labels,
padding, standalone: false, themeColor, width: chartSize.width, y: primarySegmentedMeasureDataY }, primarySegmentedMeasureComponent.props));
// Qualitative range
const qualitativeRange = React.cloneElement(qualitativeRangeComponent, Object.assign({ allowTooltip,
constrainToVisibleArea, barWidth: getQualitativeRangeBarWidth({ height: chartSize.height, horizontal, width: chartSize.width }), data: qualitativeRangeData, domain, height: chartSize.height, horizontal,
invert, labelComponent: allowTooltip ? React.createElement(ChartTooltip, { height: height, theme: theme, width: width }) : undefined, labels,
padding, standalone: false, width: chartSize.width, y: qualitativeRangeDataY, y0: qualitativeRangeDataY0 }, qualitativeRangeComponent.props));
// Returns tick values -- Victory doesn't include min/max domain
const getTickValues = (minVal, maxVal) => {
const tickValues = [minVal, maxVal];
let range = 0;
if (minVal < 0 && maxVal < 0) {
range = Math.abs(minVal - maxVal);
}
else if (minVal < 0) {
range = Math.abs(minVal) + maxVal;
}
else {
range = maxVal - minVal;
}
const tickInterval = range / (ChartBulletStyles.axisTickCount - 1);
for (let i = minVal; i < maxVal;) {
i += tickInterval;
tickValues.push(Math.ceil(i));
}
return tickValues;
};
// Returns a computed legend
const getLegend = () => {
if (!legend.props.data) {
return null;
}
let dx = 0;
let dy = 0;
// Adjust for padding
if (legendPosition === ChartLegendPosition.bottom) {
if (horizontal) {
dy = defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - defaultPadding.bottom) - 25;
}
else if (title) {
dy = -defaultPadding.bottom + 60;
}
else {
dy = -defaultPadding.bottom;
}
}
else if (legendPosition === ChartLegendPosition.bottomLeft) {
if (horizontal) {
dy = defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - defaultPadding.bottom) - 25;
}
else if (title) {
dy = -defaultPadding.bottom + 60;
}
else {
dy = -defaultPadding.bottom;
}
dx = -10;
}
return getComputedLegend({
allowWrap: legendAllowWrap,
chartType: 'bullet',
dx,
dy,
height: chartSize.height,
legendComponent: legend,
padding: defaultPadding,
position: legendPosition,
theme,
width: chartSize.width
});
};
// Returns comparative zero measure
const getComparativeZeroMeasure = () => {
const _domain = domain;
let low = 0;
if (Array.isArray(_domain)) {
low = _domain[0];
}
else if (_domain.y && Array.isArray(_domain.y)) {
low = _domain.y[0];
}
let high = 0;
if (Array.isArray(_domain)) {
high = _domain[_domain.length - 1];
}
else if (_domain.y && Array.isArray(_domain.y)) {
high = _domain.y[_domain.y.length - 1];
}
if (low < 0 && high > 0) {
return comparativeZeroMeasure;
}
return null;
};
// Axis component for custom tick values
const axis = React.cloneElement(axisComponent, Object.assign(Object.assign(Object.assign({ dependentAxis: horizontal ? false : true, domain: !horizontal
? domain
: {
x: domain.y,
y: domain.x
}, height: chartSize.height }, (name && { name: `${name}-${axisComponent.type.displayName}` })), {
// Adjust for padding
offsetX: !horizontal ? defaultPadding.left * 0.5 + (defaultPadding.right * 0.5 - (defaultPadding.right - 55)) : 0, offsetY: horizontal ? 80 - defaultPadding.top * 0.5 + (defaultPadding.bottom * 0.5 - 25) : 0, padding, standalone: false, tickCount: ChartBulletStyles.axisTickCount, tickValues: getTickValues(domain.y[0], domain.y[1]), width: chartSize.width }), axisComponent.props));
const bulletChart = (React.createElement(React.Fragment, null,
axis,
bulletGroupTitle,
bulletTitle,
qualitativeRange,
primarySegmentedMeasure,
primaryDotMeasure,
comparativeErrorMeasure,
comparativeWarningMeasure,
getComparativeZeroMeasure(),
getLegend()));
return standalone ? (React.createElement(ChartContainer, { desc: ariaDesc, height: height, title: ariaTitle, theme: theme, width: width }, bulletChart)) : (React.createElement(React.Fragment, null, bulletChart));
};
ChartBullet.displayName = 'ChartBullet';
hoistNonReactStatics(ChartBullet, VictoryChart);
//# sourceMappingURL=ChartBullet.js.map