@grafana/ui
Version:
Grafana Components Library
1 lines • 16.2 kB
Source Map (JSON)
{"version":3,"file":"UPlotAxisBuilder.mjs","sources":["../../../../../src/components/uPlot/config/UPlotAxisBuilder.ts"],"sourcesContent":["import uPlot, { Axis } from 'uplot';\n\nimport {\n dateTimeFormat,\n DecimalCount,\n GrafanaTheme2,\n guessDecimals,\n isBooleanUnit,\n roundDecimals,\n systemDateFormats,\n TimeZone,\n} from '@grafana/data';\nimport { AxisPlacement, ScaleDistribution } from '@grafana/schema';\n\nimport { measureText } from '../../../utils/measureText';\nimport { PlotConfigBuilder } from '../types';\n\nimport { optMinMax } from './UPlotScaleBuilder';\n\nexport interface AxisProps {\n scaleKey: string;\n theme: GrafanaTheme2;\n label?: string;\n show?: boolean;\n size?: number | null;\n gap?: number;\n tickLabelRotation?: number;\n placement?: AxisPlacement;\n grid?: Axis.Grid;\n ticks?: Axis.Ticks;\n filter?: Axis.Filter;\n space?: Axis.Space;\n formatValue?: (v: any, decimals?: DecimalCount) => string;\n incrs?: Axis.Incrs;\n splits?: Axis.Splits;\n values?: Axis.Values;\n isTime?: boolean;\n timeZone?: TimeZone;\n color?: uPlot.Axis.Stroke;\n border?: uPlot.Axis.Border;\n decimals?: DecimalCount;\n distr?: ScaleDistribution;\n}\n\nexport const UPLOT_AXIS_FONT_SIZE = 12;\n\n// for panels with small heights, we increase tick density by reducing the minumum tick spacing\n// all values in CSS pixels\nconst Y_TICK_SPACING_PANEL_HEIGHT = 150;\nconst Y_TICK_SPACING_NORMAL = 30;\nconst Y_TICK_SPACING_SMALL = 15;\n\nconst X_TICK_SPACING_NORMAL = 40;\nconst X_TICK_VALUE_GAP = 18;\n\nconst labelPad = 8;\n\nexport class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {\n merge(props: AxisProps) {\n this.props.size = optMinMax('max', this.props.size, props.size);\n if (!this.props.label) {\n this.props.label = props.label;\n }\n if (this.props.placement === AxisPlacement.Auto) {\n this.props.placement = props.placement;\n }\n }\n\n getConfig(): Axis {\n let {\n scaleKey,\n label,\n show = true,\n placement = AxisPlacement.Auto,\n grid = { show: true },\n ticks,\n space,\n filter,\n gap = 5,\n formatValue,\n splits,\n values,\n incrs,\n isTime,\n timeZone,\n theme,\n tickLabelRotation,\n size,\n color,\n border,\n decimals,\n distr = ScaleDistribution.Linear,\n } = this.props;\n\n const font = `${UPLOT_AXIS_FONT_SIZE}px ${theme.typography.fontFamily}`;\n\n const gridColor = theme.isDark ? 'rgba(240, 250, 255, 0.09)' : 'rgba(0, 10, 23, 0.09)';\n\n // TODO: this is pretty flimsy now that scaleKey is composed from multiple parts :/\n if (isBooleanUnit(scaleKey)) {\n splits = [0, 1];\n }\n\n if (decimals === 0 && distr === ScaleDistribution.Linear) {\n filter = (u, splits) => splits.map((v) => (Number.isInteger(v) ? v : null));\n }\n\n let config: Axis = {\n scale: scaleKey,\n show,\n stroke: color ?? theme.colors.text.primary,\n side: getUPlotSideFromAxis(placement),\n font,\n size:\n size ??\n ((self, values, axisIdx) => {\n return calculateAxisSize(self, values, axisIdx);\n }),\n rotate: tickLabelRotation,\n gap,\n\n labelGap: 0,\n\n grid: {\n show: grid.show,\n stroke: gridColor,\n width: 1 / devicePixelRatio,\n },\n ticks: Object.assign(\n {\n show: true,\n stroke: border?.show ? (color ?? theme.colors.text.primary) : gridColor,\n width: 1 / devicePixelRatio,\n size: 4,\n },\n ticks\n ),\n splits,\n values,\n space:\n space ??\n ((self, axisIdx, scaleMin, scaleMax, plotDim) => {\n return calculateSpace(self, axisIdx, scaleMin, scaleMax, plotDim, formatValue);\n }),\n filter,\n incrs,\n };\n\n if (border?.show) {\n config.border = {\n stroke: color ?? theme.colors.text.primary,\n width: 1 / devicePixelRatio,\n ...border,\n };\n }\n\n if (label != null && label.length > 0) {\n config.label = label;\n config.labelSize = UPLOT_AXIS_FONT_SIZE + labelPad;\n config.labelFont = font;\n config.labelGap = labelPad;\n }\n\n if (values) {\n config.values = values;\n } else if (formatValue) {\n config.values = (u: uPlot, splits, axisIdx, tickSpace, tickIncr) => {\n let decimals = guessDecimals(roundDecimals(tickIncr, 6));\n return splits.map((v) => {\n if (v == null) {\n return null;\n } else {\n return formatValue!(v, decimals > 0 ? decimals : undefined);\n }\n });\n };\n } else if (isTime) {\n config.values = formatTime;\n }\n\n // store timezone\n (config as any).timeZone = timeZone;\n\n return config;\n }\n}\n\n/** @internal */\nexport const timeUnitSize = {\n second: 1000,\n minute: 60 * 1000,\n hour: 60 * 60 * 1000,\n day: 24 * 60 * 60 * 1000,\n month: 28 * 24 * 60 * 60 * 1000,\n year: 365 * 24 * 60 * 60 * 1000,\n};\n\n/** Format time axis ticks */\nexport function formatTime(\n self: uPlot,\n splits: number[],\n axisIdx: number,\n foundSpace: number,\n foundIncr: number\n): string[] {\n const axis = self.axes[axisIdx];\n const timeZone = 'timeZone' in axis && typeof axis.timeZone === 'string' ? axis.timeZone : undefined;\n const scale = self.scales.x;\n const range = (scale?.max ?? 0) - (scale?.min ?? 0);\n const yearRoundedToDay = Math.round(timeUnitSize.year / timeUnitSize.day) * timeUnitSize.day;\n const incrementRoundedToDay = Math.round(foundIncr / timeUnitSize.day) * timeUnitSize.day;\n\n let format = systemDateFormats.interval.year;\n\n if (foundIncr < timeUnitSize.second) {\n format = systemDateFormats.interval.millisecond;\n } else if (foundIncr <= timeUnitSize.minute) {\n format = systemDateFormats.interval.second;\n } else if (range <= timeUnitSize.day) {\n format = systemDateFormats.interval.minute;\n } else if (foundIncr <= timeUnitSize.day) {\n format = systemDateFormats.interval.hour;\n } else if (range < timeUnitSize.year) {\n format = systemDateFormats.interval.day;\n } else if (incrementRoundedToDay === yearRoundedToDay) {\n format = systemDateFormats.interval.year;\n } else if (foundIncr <= timeUnitSize.year) {\n format = systemDateFormats.interval.month;\n }\n\n return splits.map((v) => (v == null ? '' : dateTimeFormat(v, { format, timeZone })));\n}\n\n/* Minimum grid & tick spacing in CSS pixels */\nfunction calculateSpace(\n self: uPlot,\n axisIdx: number,\n scaleMin: number,\n scaleMax: number,\n plotDim: number,\n formatValue?: (value: unknown) => string\n): number {\n const axis = self.axes[axisIdx];\n const scale = self.scales[axis.scale!];\n\n // for axis left & right\n if (axis.side !== 2 || !scale) {\n return plotDim <= Y_TICK_SPACING_PANEL_HEIGHT ? Y_TICK_SPACING_SMALL : Y_TICK_SPACING_NORMAL;\n }\n\n const maxTicks = plotDim / X_TICK_SPACING_NORMAL;\n const increment = (scaleMax - scaleMin) / maxTicks;\n\n // not super great, since 0.000005 has many more chars than 1.0\n // it also doesn't work well with \"short\" or adaptive units, e.g. 7 K and 6.40 K\n const bigValue = Math.max(Math.abs(scaleMin), Math.abs(scaleMax));\n\n let sample = '';\n\n if (scale.time) {\n sample = formatTime(self, [bigValue], axisIdx, X_TICK_SPACING_NORMAL, increment)[0];\n } else if (formatValue != null) {\n sample = formatValue(bigValue);\n } else {\n return X_TICK_SPACING_NORMAL;\n }\n\n const valueWidth = measureText(sample, UPLOT_AXIS_FONT_SIZE).width;\n\n return valueWidth + X_TICK_VALUE_GAP;\n}\n\n/** height of x axis or width of y axis in CSS pixels alloted for values, gap & ticks, but excluding axis label */\nfunction calculateAxisSize(self: uPlot, values: string[], axisIdx: number) {\n const axis = self.axes[axisIdx];\n\n let axisSize = axis.ticks!.size!;\n\n if (axis.side === 2) {\n axisSize += axis!.gap! + UPLOT_AXIS_FONT_SIZE;\n } else if (values?.length) {\n let maxTextWidth = values.reduce((acc, value) => Math.max(acc, measureText(value, UPLOT_AXIS_FONT_SIZE).width), 0);\n // limit y tick label width to 40% of visualization\n const textWidthWithLimit = Math.min(self.width * 0.4, maxTextWidth);\n // Not sure why this += and not normal assignment\n axisSize += axis!.gap! + axis!.labelGap! + textWidthWithLimit;\n }\n\n return Math.ceil(axisSize);\n}\n\nexport function getUPlotSideFromAxis(axis: AxisPlacement) {\n switch (axis) {\n case AxisPlacement.Top:\n return 0;\n case AxisPlacement.Right:\n return 1;\n case AxisPlacement.Bottom:\n return 2;\n case AxisPlacement.Left:\n }\n\n return 3; // default everythign to the left\n}\n"],"names":["splits","values","decimals"],"mappings":"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"}