UNPKG

@grafana/ui

Version:
495 lines (492 loc) • 16 kB
import { jsx } from 'react/jsx-runtime'; import tinycolor from 'tinycolor2'; import { FieldType, formattedValueToString } from '@grafana/data'; import { GraphDrawStyle, PercentChangeColorMode } from '@grafana/schema'; import { getTextColorForAlphaBackground } from '../../utils/colors.mjs'; import { calculateFontSize } from '../../utils/measureText.mjs'; import { Sparkline } from '../Sparkline/Sparkline.mjs'; import { BigValueColorMode, BigValueTextMode, BigValueJustifyMode } from './BigValue.mjs'; import { percentChangeString } from './PercentChange.mjs'; "use strict"; const LINE_HEIGHT = 1.2; const MAX_TITLE_SIZE = 30; const VALUE_FONT_WEIGHT = 500; class BigValueLayout { constructor(props) { this.props = props; var _a; const { width, height, value, text } = props; this.valueColor = (_a = value.color) != null ? _a : "gray"; this.panelPadding = height > 100 ? 12 : 8; this.textValues = getTextValues(props); this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title); this.valueToAlignTo = this.textValues.valueToAlignTo; this.titleToAlignTo = this.textValues.titleToAlignTo; this.titleFontSize = 0; this.valueFontSize = 0; this.percentFontSize = 0; this.chartHeight = 0; this.chartWidth = 0; this.maxTextWidth = width - this.panelPadding * 2; this.maxTextHeight = height - this.panelPadding * 2; if (text) { if (text.titleSize) { this.titleFontSize = text.titleSize; this.titleToAlignTo = void 0; } if (text.valueSize) { this.valueFontSize = text.valueSize; this.valueToAlignTo = ""; } if (text.percentSize) { this.percentFontSize = text.percentSize; } } } getTitleStyles() { const styles = { fontSize: `${this.titleFontSize}px`, lineHeight: LINE_HEIGHT }; if (this.props.colorMode === BigValueColorMode.Background || this.props.colorMode === BigValueColorMode.BackgroundSolid) { styles.color = getTextColorForAlphaBackground(this.valueColor, this.props.theme.isDark); } return styles; } getValueStyles() { const styles = { fontSize: this.valueFontSize, fontWeight: VALUE_FONT_WEIGHT, lineHeight: LINE_HEIGHT, position: "relative", zIndex: 1 }; if (this.justifyCenter) { styles.textAlign = "center"; } switch (this.props.colorMode) { case BigValueColorMode.Value: styles.color = this.valueColor; break; case BigValueColorMode.Background: case BigValueColorMode.BackgroundSolid: styles.color = getTextColorForAlphaBackground(this.valueColor, this.props.theme.isDark); break; case BigValueColorMode.None: styles.color = this.props.theme.colors.text.primary; break; } return styles; } getPercentChangeStyles(percentChange, percentChangeColorMode, valueStyles) { const VALUE_TO_PERCENT_CHANGE_RATIO = 2.5; const valueContainerStyles = this.getValueAndTitleContainerStyles(); const percentFontSize = this.percentFontSize || Math.max(this.valueFontSize / VALUE_TO_PERCENT_CHANGE_RATIO, 12); let iconSize = this.percentFontSize ? this.percentFontSize - 3 : Math.max(this.valueFontSize / 3, 10); const themeVisualizationColors = this.props.theme.visualization; const color = getPercentChangeColor(percentChange, percentChangeColorMode, valueStyles, themeVisualizationColors); const containerStyles = { fontSize: percentFontSize, fontWeight: VALUE_FONT_WEIGHT, lineHeight: LINE_HEIGHT, position: "relative", display: "flex", alignItems: "center", gap: Math.max(percentFontSize / 3, 4), zIndex: 1, color }; if (this.justifyCenter) { containerStyles.textAlign = "center"; } if (valueContainerStyles.flexDirection === "column" && percentFontSize > 12) { containerStyles.marginTop = -(percentFontSize / 4); } if (valueContainerStyles.flexDirection === "row") { containerStyles.alignItems = "baseline"; containerStyles.lineHeight = LINE_HEIGHT * VALUE_TO_PERCENT_CHANGE_RATIO; } switch (this.props.colorMode) { case BigValueColorMode.Background: case BigValueColorMode.BackgroundSolid: containerStyles.color = getTextColorForAlphaBackground(this.valueColor, this.props.theme.isDark); break; } if (this.props.textMode === BigValueTextMode.None) { containerStyles.fontSize = calculateFontSize( percentChangeString(percentChange), this.maxTextWidth * 0.8, this.maxTextHeight * 0.8, LINE_HEIGHT, void 0, VALUE_FONT_WEIGHT ); iconSize = containerStyles.fontSize * 0.8; } return { containerStyles, iconSize }; } getValueAndTitleContainerStyles() { const styles = { display: "flex", flexWrap: "wrap" }; if (this.justifyCenter) { styles.alignItems = "center"; styles.justifyContent = "center"; styles.flexGrow = 1; styles.gap = "0.75ch"; } return styles; } getPanelStyles() { const { width, height, theme, colorMode, textMode } = this.props; const panelStyles = { width: `${width}px`, height: `${height}px`, padding: `${textMode === BigValueTextMode.None ? 2 : this.panelPadding}px`, position: "relative", display: "flex" }; const themeFactor = theme.isDark ? 1 : -0.7; switch (colorMode) { case BigValueColorMode.Background: const bgColor2 = tinycolor(this.valueColor).darken(15 * themeFactor).spin(8).toRgbString(); const bgColor3 = tinycolor(this.valueColor).darken(5 * themeFactor).spin(-8).toRgbString(); panelStyles.background = `linear-gradient(120deg, ${bgColor2}, ${bgColor3})`; break; case BigValueColorMode.BackgroundSolid: panelStyles.background = tinycolor(this.valueColor).toString(); break; case BigValueColorMode.Value: panelStyles.background = `transparent`; break; } if (this.justifyCenter) { panelStyles.alignItems = "center"; panelStyles.flexDirection = "row"; } return panelStyles; } renderChart() { var _a; const { sparkline, colorMode } = this.props; if (!sparkline || ((_a = sparkline.y) == null ? void 0 : _a.type) !== FieldType.number) { return null; } let fillColor; let lineColor; switch (colorMode) { case BigValueColorMode.Background: case BigValueColorMode.BackgroundSolid: fillColor = "rgba(255,255,255,0.4)"; lineColor = tinycolor(this.valueColor).brighten(40).toRgbString(); break; case BigValueColorMode.None: case BigValueColorMode.Value: default: lineColor = this.valueColor; fillColor = tinycolor(this.valueColor).setAlpha(0.2).toRgbString(); break; } const config = { custom: { drawStyle: GraphDrawStyle.Line, lineWidth: 1, fillColor, lineColor } }; return /* @__PURE__ */ jsx("div", { style: this.getChartStyles(), children: /* @__PURE__ */ jsx( Sparkline, { height: this.chartHeight, width: this.chartWidth, sparkline, config, theme: this.props.theme } ) }); } getChartStyles() { return { position: "absolute", right: 0, bottom: 0 }; } } class WideNoChartLayout extends BigValueLayout { constructor(props) { var _a, _b; super(props); const valueWidthPercent = ((_a = this.titleToAlignTo) == null ? void 0 : _a.length) ? 0.3 : 1; if (this.valueToAlignTo.length) { let valueHeight = this.maxTextHeight; if (props.value.percentChange != null) { valueHeight = valueHeight * 0.75; } this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth * valueWidthPercent, valueHeight, LINE_HEIGHT, void 0, VALUE_FONT_WEIGHT ); } if ((_b = this.titleToAlignTo) == null ? void 0 : _b.length) { this.titleFontSize = calculateFontSize( this.titleToAlignTo, this.maxTextWidth * 0.6, this.maxTextHeight, LINE_HEIGHT, MAX_TITLE_SIZE ); this.titleFontSize = Math.min(this.valueFontSize * 0.7, this.titleFontSize); } } getValueAndTitleContainerStyles() { const styles = super.getValueAndTitleContainerStyles(); styles.flexDirection = "row"; styles.alignItems = "center"; styles.flexGrow = 1; if (!this.justifyCenter) { styles.justifyContent = "space-between"; } return styles; } renderChart() { return null; } getPanelStyles() { const panelStyles = super.getPanelStyles(); panelStyles.alignItems = "center"; return panelStyles; } } class WideWithChartLayout extends BigValueLayout { constructor(props) { var _a; super(props); const { width, height } = props; const chartHeightPercent = 0.5; const titleWidthPercent = 0.6; const valueWidthPercent = 1 - titleWidthPercent; const textHeightPercent = 0.4; this.chartWidth = width; this.chartHeight = height * chartHeightPercent; if ((_a = this.titleToAlignTo) == null ? void 0 : _a.length) { this.titleFontSize = calculateFontSize( this.titleToAlignTo, this.maxTextWidth * titleWidthPercent, this.maxTextHeight * textHeightPercent, LINE_HEIGHT, MAX_TITLE_SIZE ); } if (this.valueToAlignTo.length) { this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth * valueWidthPercent, this.maxTextHeight * chartHeightPercent, LINE_HEIGHT, void 0, VALUE_FONT_WEIGHT ); } } getValueAndTitleContainerStyles() { const styles = super.getValueAndTitleContainerStyles(); styles.flexDirection = "row"; styles.flexGrow = 1; if (!this.justifyCenter) { styles.justifyContent = "space-between"; } return styles; } getPanelStyles() { const styles = super.getPanelStyles(); styles.flexDirection = "row"; styles.justifyContent = "space-between"; return styles; } } class StackedWithChartLayout extends BigValueLayout { constructor(props) { var _a, _b; super(props); const { width, height } = props; const titleHeightPercent = 0.15; const chartHeightPercent = 0.25; let titleHeight = 0; this.chartHeight = height * chartHeightPercent; this.chartWidth = width; if ((_a = this.titleToAlignTo) == null ? void 0 : _a.length) { this.titleFontSize = calculateFontSize( this.titleToAlignTo, this.maxTextWidth, height * titleHeightPercent, LINE_HEIGHT, MAX_TITLE_SIZE ); titleHeight = this.titleFontSize * LINE_HEIGHT; } if (this.valueToAlignTo.length) { this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth, this.maxTextHeight - this.chartHeight - titleHeight, LINE_HEIGHT, void 0, VALUE_FONT_WEIGHT ); } if ((_b = this.titleToAlignTo) == null ? void 0 : _b.length) { this.titleFontSize = Math.min(this.valueFontSize * 0.7, this.titleFontSize); } this.chartHeight = height - this.titleFontSize * LINE_HEIGHT - this.valueFontSize * LINE_HEIGHT; } getValueAndTitleContainerStyles() { const styles = super.getValueAndTitleContainerStyles(); styles.flexDirection = "column"; styles.justifyContent = "center"; return styles; } getPanelStyles() { const styles = super.getPanelStyles(); styles.flexDirection = "column"; return styles; } } class StackedWithNoChartLayout extends BigValueLayout { constructor(props) { var _a, _b; super(props); const { height } = props; const titleHeightPercent = 0.15; let titleHeight = 0; if ((_a = this.titleToAlignTo) == null ? void 0 : _a.length) { this.titleFontSize = calculateFontSize( this.titleToAlignTo, this.maxTextWidth, height * titleHeightPercent, LINE_HEIGHT, MAX_TITLE_SIZE ); titleHeight = this.titleFontSize * LINE_HEIGHT; } if (this.valueToAlignTo.length) { let valueHeight = this.maxTextHeight - titleHeight; if (props.value.percentChange != null) { valueHeight = valueHeight * 0.75; } this.valueFontSize = calculateFontSize( this.valueToAlignTo, this.maxTextWidth, valueHeight, LINE_HEIGHT, void 0, VALUE_FONT_WEIGHT ); } if ((_b = this.titleToAlignTo) == null ? void 0 : _b.length) { this.titleFontSize = Math.min(this.valueFontSize * 0.7, this.titleFontSize); } } getValueAndTitleContainerStyles() { const styles = super.getValueAndTitleContainerStyles(); styles.flexDirection = "column"; styles.flexGrow = 1; return styles; } renderChart() { return null; } getPanelStyles() { const styles = super.getPanelStyles(); styles.alignItems = "center"; return styles; } } function buildLayout(props) { const { width, height, sparkline } = props; const useWideLayout = width / height > 2.5 && !props.disableWideLayout; if (useWideLayout) { if (height > 50 && !!sparkline && sparkline.y.values.length > 1) { return new WideWithChartLayout(props); } else { return new WideNoChartLayout(props); } } if (height > 100 && sparkline && sparkline.y.values.length > 1) { return new StackedWithChartLayout(props); } else { return new StackedWithNoChartLayout(props); } } function shouldJustifyCenter(justifyMode, title) { if (justifyMode === BigValueJustifyMode.Center) { return true; } return (title != null ? title : "").length === 0; } function getTextValues(props) { const { value, alignmentFactors, count } = props; let { textMode } = props; const titleToAlignTo = alignmentFactors ? alignmentFactors.title : value.title; const valueToAlignTo = formattedValueToString(alignmentFactors ? alignmentFactors : value); if (textMode === BigValueTextMode.Auto && (count != null ? count : 1) === 1) { textMode = BigValueTextMode.Value; } switch (textMode) { case BigValueTextMode.Name: return { ...value, title: void 0, prefix: void 0, suffix: void 0, text: value.title || "", titleToAlignTo: void 0, valueToAlignTo: titleToAlignTo != null ? titleToAlignTo : "", tooltip: formattedValueToString(value) }; case BigValueTextMode.Value: return { ...value, title: void 0, titleToAlignTo: void 0, valueToAlignTo, tooltip: value.title }; case BigValueTextMode.None: return { numeric: value.numeric, color: value.color, title: void 0, text: "", titleToAlignTo: void 0, valueToAlignTo: "1", tooltip: `Name: ${value.title} Value: ${formattedValueToString(value)}` }; case BigValueTextMode.ValueAndName: default: return { ...value, titleToAlignTo, valueToAlignTo }; } } function getPercentChangeColor(percentChange, percentChangeColorMode, valueStyles, themeVisualizationColors) { if (percentChangeColorMode === PercentChangeColorMode.SameAsValue) { return valueStyles.color; } else { return percentChange * (percentChangeColorMode === PercentChangeColorMode.Inverted ? -1 : 1) > 0 ? themeVisualizationColors.getColorByName("green") : themeVisualizationColors.getColorByName("red"); } } export { BigValueLayout, StackedWithChartLayout, StackedWithNoChartLayout, WideNoChartLayout, WideWithChartLayout, buildLayout, getPercentChangeColor, shouldJustifyCenter }; //# sourceMappingURL=BigValueLayout.mjs.map