UNPKG

@patternfly/react-charts

Version:

This library provides a set of React chart components for use with the PatternFly reference implementation.

371 lines • 13.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLegendItemsExtraHeight = exports.getLegendDimensions = exports.getComputedLegend = exports.getLegendMaxTextWidth = void 0; const tslib_1 = require("tslib"); const react_1 = require("react"); const defaults_1 = tslib_1.__importDefault(require("lodash/defaults")); const victory_core_1 = require("victory-core"); const victory_legend_1 = require("victory-legend"); const ChartStyles_1 = require("../ChartTheme/ChartStyles"); const chart_label_1 = require("../ChartUtils/chart-label"); const chart_origin_1 = require("./chart-origin"); /** * Returns the max text length in a legend data set to calculate the x offset for right aligned legends. * * @private Not intended as public API and subject to change */ const getLegendMaxTextWidth = (legendData, theme) => { let legendXOffset = 0; legendData.map((data) => { const labelWidth = (0, chart_label_1.getLabelTextSize)({ text: data.name, theme }).width; if (labelWidth > legendXOffset) { legendXOffset = labelWidth; } }); return legendXOffset; }; exports.getLegendMaxTextWidth = getLegendMaxTextWidth; /** * Returns a legend which has been positioned per the given chart properties * * @private Not intended as public API and subject to change */ const getComputedLegend = ({ allowWrap = true, chartType = 'chart', colorScale, dx = 0, dy = 0, height, legendComponent, padding, patternScale, position = ChartStyles_1.ChartCommonStyles.legend.position, theme, themeColor, width, // destructure last orientation = theme.legend.orientation }) => { // Get the number of legend items per row const legendItemsProps = legendComponent.props ? legendComponent.props : {}; const legendItemsPerRow = allowWrap ? getLegendItemsPerRow({ dx, height, legendData: legendItemsProps.data, legendOrientation: legendItemsProps.legendOrientation ? legendItemsProps.legendOrientation : orientation, legendPosition: position, legendProps: legendItemsProps, padding, theme, width }) : undefined; // Include new itemsPerRow prop when determining x and y position const legendPositionProps = (0, defaults_1.default)({}, legendComponent.props, { itemsPerRow: legendItemsPerRow }); const legendX = getLegendX({ chartType, dx, height, legendData: legendPositionProps.data, legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, legendPosition: position, legendProps: legendPositionProps, padding, theme, width }); const legendY = getLegendY({ chartType, dy, height, legendData: legendPositionProps.data, legendOrientation: legendPositionProps.legendOrientation ? legendPositionProps.legendOrientation : orientation, legendProps: legendPositionProps, legendPosition: position, padding, theme, width }); // Clone legend with updated props const legendProps = (0, defaults_1.default)({}, legendComponent.props, { colorScale, itemsPerRow: legendItemsPerRow, orientation, patternScale, standalone: false, theme, themeColor, x: legendX > 0 ? legendX : 0, y: legendY > 0 ? legendY : 0 }); return (0, react_1.cloneElement)(legendComponent, legendProps); }; exports.getComputedLegend = getComputedLegend; /** * Returns legend dimensions * * @private Not intended as public API and subject to change */ const getLegendDimensions = ({ legendData, legendOrientation, legendProps, theme }) => { if (legendData || legendProps.data) { return victory_legend_1.VictoryLegend.getDimensions(Object.assign({ data: legendData, orientation: legendOrientation, theme }, legendProps // override above )); } return {}; }; exports.getLegendDimensions = getLegendDimensions; /** * Returns true if the legend is smaller than its container * * @private Not intended as public API and subject to change */ const doesLegendFit = ({ dx = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => { const { left, right } = victory_core_1.Helpers.getPadding(padding); const chartSize = { height, // Fixed size width: width - left - right }; const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); let occupiedWidth = 0; switch (legendPosition) { case 'bottom-left': occupiedWidth = left + dx; break; case 'right': occupiedWidth = chartSize.width + ChartStyles_1.ChartCommonStyles.legend.margin + left + dx; break; default: occupiedWidth = dx; break; } return width - occupiedWidth > legendDimensions.width; }; /** * Returns the number of legend items per row * * @private Not intended as public API and subject to change */ const getLegendItemsPerRow = ({ dx, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => { let itemsPerRow = legendData ? legendData.length : 0; for (let i = itemsPerRow; i > 0; i--) { const fits = doesLegendFit({ dx, height, legendPosition, legendData, legendOrientation, legendProps: Object.assign(Object.assign({}, legendProps), { itemsPerRow: i }), padding, theme, width }); if (fits) { itemsPerRow = i; break; } } return itemsPerRow; }; /** * Returns the extra height required to accommodate wrapped legend items * * @private Not intended as public API and subject to change */ const getLegendItemsExtraHeight = ({ legendData, legendOrientation, legendProps, theme }) => { // Get legend dimensions const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); // Get legend dimensions without any wrapped items const legendDimensionsNoWrap = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps: Object.assign(Object.assign({}, legendProps), { itemsPerRow: undefined }), theme }); return Math.abs(legendDimensions.height - legendDimensionsNoWrap.height); }; exports.getLegendItemsExtraHeight = getLegendItemsExtraHeight; /** * Returns x coordinate for legend * * @private Not intended as public API and subject to change */ const getLegendX = (_a) => { var { chartType } = _a, rest = tslib_1.__rest(_a, ["chartType"]); return chartType === 'pie' ? getPieLegendX(rest) : getChartLegendX(rest); }; /** * Returns y coordinate for legend * * @private Not intended as public API and subject to change */ const getLegendY = (_a) => { var { chartType } = _a, rest = tslib_1.__rest(_a, ["chartType"]); switch (chartType) { case 'pie': return getPieLegendY(rest); case 'bullet': return getBulletLegendY(rest); default: return getChartLegendY(rest); } }; /** * Returns y coordinate for bullet legends * * @private Not intended as public API and subject to change */ const getBulletLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => { const { left, right } = victory_core_1.Helpers.getPadding(padding); const chartSize = { height, // Fixed size width: width - left - right }; switch (legendPosition) { case 'bottom': case 'bottom-left': return chartSize.height + ChartStyles_1.ChartCommonStyles.legend.margin + dy; case 'right': { // Legend height with padding const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 17 : 0); return (chartSize.height - legendDimensions.height) / 2 + legendPadding(legendData); } default: return dy; } }; /** * Returns x coordinate for chart legends * * @private Not intended as public API and subject to change */ const getChartLegendX = ({ dx = 0, height, legendData, legendOrientation, legendPosition, legendProps, padding, theme, width }) => { const { top, bottom, left, right } = victory_core_1.Helpers.getPadding(padding); const chartSize = { height: Math.abs(height - (bottom + top)), width: Math.abs(width - (left + right)) }; const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); switch (legendPosition) { case 'bottom': return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; case 'bottom-left': return left + dx; case 'right': return chartSize.width + ChartStyles_1.ChartCommonStyles.legend.margin + left + dx; default: return dx; } }; /** * Returns y coordinate for chart legends * * @private Not intended as public API and subject to change */ const getChartLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => { const { top, bottom, left, right } = victory_core_1.Helpers.getPadding(padding); const chartSize = { height: Math.abs(height - (bottom + top)), width: Math.abs(width - (left + right)) }; switch (legendPosition) { case 'bottom': case 'bottom-left': return chartSize.height + ChartStyles_1.ChartCommonStyles.legend.margin * 2 + top + dy; case 'right': { // Legend height with padding const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); const originX = chartSize.height / 2 + top; const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); return originX - legendDimensions.height / 2 + legendPadding(legendData); } default: return dy; } }; /** * Returns x coordinate for pie legends * * @private Not intended as public API and subject to change */ const getPieLegendX = ({ dx = 0, height, legendData, legendOrientation, legendPosition, legendProps, padding, theme, width }) => { const origin = (0, chart_origin_1.getPieOrigin)({ height, padding, width }); const radius = victory_core_1.Helpers.getRadius({ height, width, padding }); const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); switch (legendPosition) { case 'bottom': return width > legendDimensions.width ? Math.round((width - legendDimensions.width) / 2) + dx : dx; case 'right': return origin.x + ChartStyles_1.ChartCommonStyles.label.margin + dx + radius; default: return dx; } }; /** * Returns y coordinate for pie legends * * @private Not intended as public API and subject to change */ const getPieLegendY = ({ dy = 0, height, legendPosition, legendData, legendOrientation, legendProps, padding, theme, width }) => { const origin = (0, chart_origin_1.getPieOrigin)({ height, padding, width }); const radius = victory_core_1.Helpers.getRadius({ height, width, padding }); switch (legendPosition) { case 'bottom': return origin.y + ChartStyles_1.ChartCommonStyles.legend.margin + radius + dy; case 'right': { // Legend height with padding const legendDimensions = (0, exports.getLegendDimensions)({ legendData, legendOrientation, legendProps, theme }); const legendPadding = (legendDataArr) => (legendDataArr && legendDataArr.length > 0 ? 2 : 0); return origin.y - legendDimensions.height / 2 + legendPadding(legendData); } default: return dy; } }; /** * Returns an approximation of longest text width based on legend styles * * @private Not intended as public API and subject to change */ // eslint-disable-next-line @typescript-eslint/no-unused-vars const getMaxLegendTextSize = ({ legendData, theme }) => { const style = theme && theme.legend && theme.legend.style ? theme.legend.style.labels : undefined; if (!(legendData && legendData.length)) { return 0; } let result = ''; legendData.forEach((data) => { if (data.name && data.name.length > result.length) { result = data.name; } }); // The approximateTextSize function returns height and width, but Victory incorrectly typed it as number const adjustedTextSize = victory_core_1.TextSize.approximateTextSize(result, Object.assign({}, style)); return adjustedTextSize.width; }; //# sourceMappingURL=chart-legend.js.map