@grafana/ui
Version:
Grafana Components Library
1 lines • 33.8 kB
Source Map (JSON)
{"version":3,"file":"utils.mjs","sources":["../../../../../src/components/Table/TableNG/utils.ts"],"sourcesContent":["import { Property } from 'csstype';\nimport { SortColumn } from 'react-data-grid';\nimport tinycolor from 'tinycolor2';\n\nimport {\n FieldType,\n Field,\n formattedValueToString,\n GrafanaTheme2,\n DisplayValue,\n LinkModel,\n DisplayValueAlignmentFactors,\n DataFrame,\n} from '@grafana/data';\nimport {\n BarGaugeDisplayMode,\n TableCellBackgroundDisplayMode,\n TableCellDisplayMode,\n TableCellHeight,\n} from '@grafana/schema';\n\nimport { getTextColorForAlphaBackground } from '../../../utils/colors';\nimport { TableCellOptions } from '../types';\n\nimport { COLUMN, TABLE } from './constants';\nimport { CellColors, TableRow, TableFieldOptionsType, ColumnTypes, FrameToRowsConverter, Comparator } from './types';\n\n/* ---------------------------- Cell calculations --------------------------- */\nexport type CellHeightCalculator = (text: string, cellWidth: number) => number;\n\n/**\n * @internal\n * Returns the default row height based on the theme and cell height setting.\n */\nexport function getDefaultRowHeight(theme: GrafanaTheme2, cellHeight?: TableCellHeight): number {\n const bodyFontSize = theme.typography.fontSize;\n const lineHeight = theme.typography.body.lineHeight;\n\n switch (cellHeight) {\n case TableCellHeight.Sm:\n return 36;\n case TableCellHeight.Md:\n return 42;\n case TableCellHeight.Lg:\n return TABLE.MAX_CELL_HEIGHT;\n }\n\n return TABLE.CELL_PADDING * 2 + bodyFontSize * lineHeight;\n}\n\n/**\n * @internal\n * Returns true if cell inspection (hover to see full content) is enabled for the field.\n */\nexport function isCellInspectEnabled(field: Field): boolean {\n return field.config?.custom?.inspect ?? false;\n}\n\n/**\n * @internal\n * Returns true if text wrapping should be applied to the cell.\n */\nexport function shouldTextWrap(field: Field): boolean {\n const cellOptions = getCellOptions(field);\n // @ts-ignore - a handful of cellTypes have boolean wrapText, but not all of them.\n // we should be very careful to only use boolean type for cellOptions.wrapText.\n // TBH we will probably move this up to a field option which is showIf rendered anyway,\n // but that'll be a migration to do, so it needs to happen post-GA.\n return Boolean(cellOptions?.wrapText);\n}\n\n// matches characters which CSS\nconst spaceRegex = /[\\s-]/;\n\nexport interface GetMaxWrapCellOptions {\n colWidths: number[];\n avgCharWidth: number;\n wrappedColIdxs: boolean[];\n}\n\n/**\n * @internal\n * loop through the fields and their values, determine which cell is going to determine the\n * height of the row based on its content and width, and then return the text, index, and number of lines for that cell.\n */\nexport function getMaxWrapCell(\n fields: Field[],\n rowIdx: number,\n { colWidths, avgCharWidth, wrappedColIdxs }: GetMaxWrapCellOptions\n): {\n text: string;\n idx: number;\n numLines: number;\n} {\n let maxLines = 1;\n let maxLinesIdx = -1;\n let maxLinesText = '';\n\n // TODO: consider changing how we store this, using a record by column key instead of an array\n for (let i = 0; i < colWidths.length; i++) {\n if (wrappedColIdxs[i]) {\n const field = fields[i];\n // special case: for the header, provide `-1` as the row index.\n const cellTextRaw = rowIdx === -1 ? getDisplayName(field) : field.values[rowIdx];\n\n if (cellTextRaw != null) {\n const cellText = String(cellTextRaw);\n\n if (spaceRegex.test(cellText)) {\n const charsPerLine = colWidths[i] / avgCharWidth;\n const approxLines = cellText.length / charsPerLine;\n\n if (approxLines > maxLines) {\n maxLines = approxLines;\n maxLinesIdx = i;\n maxLinesText = cellText;\n }\n }\n }\n }\n }\n\n return { text: maxLinesText, idx: maxLinesIdx, numLines: maxLines };\n}\n\n/**\n * @internal\n * Returns true if text overflow handling should be applied to the cell.\n */\nexport function shouldTextOverflow(field: Field): boolean {\n return (\n field.type === FieldType.string &&\n // Tech debt: Technically image cells are of type string, which is misleading (kinda?)\n // so we need to ensure we don't apply overflow hover states for type image\n getCellOptions(field).type !== TableCellDisplayMode.Image &&\n !shouldTextWrap(field) &&\n !isCellInspectEnabled(field)\n );\n}\n\n/**\n * @internal\n * Returns the text alignment for a field based on its type and configuration.\n */\nexport function getTextAlign(field?: Field): Property.JustifyContent {\n if (!field) {\n return 'flex-start';\n }\n\n if (field.config.custom) {\n const custom: TableFieldOptionsType = field.config.custom;\n\n switch (custom.align) {\n case 'right':\n return 'flex-end';\n case 'left':\n return 'flex-start';\n case 'center':\n return 'center';\n }\n }\n\n if (field.type === FieldType.number) {\n return 'flex-end';\n }\n\n return 'flex-start';\n}\n\nconst DEFAULT_CELL_OPTIONS = { type: TableCellDisplayMode.Auto } as const;\n\n/**\n * @internal\n * Returns the cell options for a field, migrating from legacy displayMode if necessary.\n * TODO: remove live migration in favor of doing it in dashboard or panel migrator\n */\nexport function getCellOptions(field: Field): TableCellOptions {\n if (field.config.custom?.displayMode) {\n return migrateTableDisplayModeToCellOptions(field.config.custom?.displayMode);\n }\n\n return field.config.custom?.cellOptions ?? DEFAULT_CELL_OPTIONS;\n}\n\n/**\n * @internal\n * Getting gauge or sparkline values to align is very tricky without looking at all values and passing them through display processor.\n * For very large tables that could pretty expensive. So this is kind of a compromise. We look at the first 1000 rows and cache the longest value.\n * If we have a cached value we just check if the current value is longer and update the alignmentFactor. This can obviously still lead to\n * unaligned gauges but it should a lot less common.\n **/\nexport function getAlignmentFactor(\n field: Field,\n displayValue: DisplayValue,\n rowIndex: number\n): DisplayValueAlignmentFactors {\n let alignmentFactor = field.state?.alignmentFactors;\n\n if (alignmentFactor) {\n // check if current alignmentFactor is still the longest\n if (formattedValueToString(alignmentFactor).length < formattedValueToString(displayValue).length) {\n alignmentFactor = { ...displayValue };\n field.state!.alignmentFactors = alignmentFactor;\n }\n return alignmentFactor;\n } else {\n // look at the next 1000 rows\n alignmentFactor = { ...displayValue };\n const maxIndex = Math.min(field.values.length, rowIndex + 1000);\n\n for (let i = rowIndex + 1; i < maxIndex; i++) {\n const nextDisplayValue = field.display?.(field.values[i]) ?? field.values[i];\n if (formattedValueToString(alignmentFactor).length > formattedValueToString(nextDisplayValue).length) {\n alignmentFactor.text = displayValue.text;\n }\n }\n\n if (field.state) {\n field.state.alignmentFactors = alignmentFactor;\n } else {\n field.state = { alignmentFactors: alignmentFactor };\n }\n\n return alignmentFactor;\n }\n}\n\n/* ------------------------- Cell color calculation ------------------------- */\nconst CELL_COLOR_DARKENING_MULTIPLIER = 10;\nconst CELL_GRADIENT_DARKENING_MULTIPLIER = 15;\nconst CELL_GRADIENT_HUE_ROTATION_DEGREES = 5;\n\n/**\n * @internal\n * Returns the text and background colors for a table cell based on its options and display value.\n */\nexport function getCellColors(\n theme: GrafanaTheme2,\n cellOptions: TableCellOptions,\n displayValue: DisplayValue\n): CellColors {\n // How much to darken elements depends upon if we're in dark mode\n const darkeningFactor = theme.isDark ? 1 : -0.7;\n\n // Setup color variables\n let textColor: string | undefined = undefined;\n let bgColor: string | undefined = undefined;\n let bgHoverColor: string | undefined = undefined;\n\n if (cellOptions.type === TableCellDisplayMode.ColorText) {\n textColor = displayValue.color;\n } else if (cellOptions.type === TableCellDisplayMode.ColorBackground) {\n const mode = cellOptions.mode ?? TableCellBackgroundDisplayMode.Gradient;\n\n if (mode === TableCellBackgroundDisplayMode.Basic) {\n textColor = getTextColorForAlphaBackground(displayValue.color!, theme.isDark);\n bgColor = tinycolor(displayValue.color).toRgbString();\n bgHoverColor = tinycolor(displayValue.color)\n .darken(CELL_COLOR_DARKENING_MULTIPLIER * darkeningFactor)\n .toRgbString();\n } else if (mode === TableCellBackgroundDisplayMode.Gradient) {\n const hoverColor = tinycolor(displayValue.color)\n .darken(CELL_GRADIENT_DARKENING_MULTIPLIER * darkeningFactor)\n .toRgbString();\n const bgColor2 = tinycolor(displayValue.color)\n .darken(CELL_COLOR_DARKENING_MULTIPLIER * darkeningFactor)\n .spin(CELL_GRADIENT_HUE_ROTATION_DEGREES);\n textColor = getTextColorForAlphaBackground(displayValue.color!, theme.isDark);\n bgColor = `linear-gradient(120deg, ${bgColor2.toRgbString()}, ${displayValue.color})`;\n bgHoverColor = `linear-gradient(120deg, ${bgColor2.toRgbString()}, ${hoverColor})`;\n }\n }\n\n return { textColor, bgColor, bgHoverColor };\n}\n\n/**\n * @internal\n * Extracts numeric pixel value from theme spacing\n */\nexport const extractPixelValue = (spacing: string | number): number => {\n return typeof spacing === 'number' ? spacing : parseFloat(spacing) || 0;\n};\n\n/* ------------------------------- Data links ------------------------------- */\n/**\n * @internal\n */\nexport const getCellLinks = (field: Field, rowIdx: number) => {\n let links: Array<LinkModel<unknown>> | undefined;\n if (field.getLinks) {\n links = field.getLinks({\n valueRowIndex: rowIdx,\n });\n }\n\n if (!links) {\n return;\n }\n\n for (let i = 0; i < links?.length; i++) {\n if (links[i].onClick) {\n const origOnClick = links[i].onClick;\n\n links[i].onClick = (event: MouseEvent) => {\n // Allow opening in new tab\n if (!(event.ctrlKey || event.metaKey || event.shiftKey)) {\n event.preventDefault();\n origOnClick!(event, {\n field,\n rowIndex: rowIdx,\n });\n }\n };\n }\n }\n\n return links.filter((link) => link.href || link.onClick != null);\n};\n\n/* ----------------------------- Data grid sorting ---------------------------- */\n/**\n * @internal\n */\nexport function applySort(\n rows: TableRow[],\n fields: Field[],\n sortColumns: SortColumn[],\n columnTypes: ColumnTypes = getColumnTypes(fields),\n hasNestedFrames: boolean = getIsNestedTable(fields)\n): TableRow[] {\n if (sortColumns.length === 0) {\n return rows;\n }\n\n const compareRows = (a: TableRow, b: TableRow): number => {\n let result = 0;\n for (let i = 0; i < sortColumns.length; i++) {\n const { columnKey, direction } = sortColumns[i];\n const compare = getComparator(columnTypes[columnKey]);\n const sortDir = direction === 'ASC' ? 1 : -1;\n\n result = sortDir * compare(a[columnKey], b[columnKey]);\n if (result !== 0) {\n break;\n }\n }\n return result;\n };\n\n // Handle nested tables\n if (hasNestedFrames) {\n return processNestedTableRows(rows, (parents) => [...parents].sort(compareRows));\n }\n\n // Regular sort for tables without nesting\n return [...rows].sort(compareRows);\n}\n\n/* ----------------------------- Data grid mapping ---------------------------- */\n/**\n * @internal\n */\nexport const frameToRecords = (frame: DataFrame): TableRow[] => {\n const fnBody = `\n const rows = Array(frame.length);\n const values = frame.fields.map(f => f.values);\n let rowCount = 0;\n for (let i = 0; i < frame.length; i++) {\n rows[rowCount] = {\n __depth: 0,\n __index: i,\n ${frame.fields.map((field, fieldIdx) => `${JSON.stringify(getDisplayName(field))}: values[${fieldIdx}][i]`).join(',')}\n };\n rowCount += 1;\n if (rows[rowCount-1]['__nestedFrames']){\n const childFrame = rows[rowCount-1]['__nestedFrames'];\n rows[rowCount] = {__depth: 1, __index: i, data: childFrame[0]}\n rowCount += 1;\n }\n }\n return rows;\n `;\n\n // Creates a function that converts a DataFrame into an array of TableRows\n // Uses new Function() for performance as it's faster than creating rows using loops\n const convert = new Function('frame', fnBody) as unknown as FrameToRowsConverter;\n return convert(frame);\n};\n\n/* ----------------------------- Data grid comparator ---------------------------- */\n// The numeric: true option is used to sort numbers as strings correctly. It recognizes numeric sequences\n// within strings and sorts numerically instead of lexicographically.\nconst compare = new Intl.Collator('en', { sensitivity: 'base', numeric: true }).compare;\nconst strCompare: Comparator = (a, b) => compare(String(a ?? ''), String(b ?? ''));\nconst numCompare: Comparator = (a, b) => {\n if (a === b) {\n return 0;\n }\n if (a == null) {\n return -1;\n }\n if (b == null) {\n return 1;\n }\n return Number(a) - Number(b);\n};\nconst frameCompare: Comparator = (a, b) => {\n // @ts-ignore The compared vals are DataFrameWithValue. the value is the rendered stat (first, last, etc.)\n return (a?.value ?? 0) - (b?.value ?? 0);\n};\n\n/**\n * @internal\n */\nexport function getComparator(sortColumnType: FieldType): Comparator {\n switch (sortColumnType) {\n // Handle sorting for frame type fields (sparklines)\n case FieldType.frame:\n return frameCompare;\n case FieldType.time:\n case FieldType.number:\n case FieldType.boolean:\n return numCompare;\n case FieldType.string:\n case FieldType.enum:\n default:\n return strCompare;\n }\n}\n\ntype TableCellGaugeDisplayModes =\n | TableCellDisplayMode.BasicGauge\n | TableCellDisplayMode.GradientGauge\n | TableCellDisplayMode.LcdGauge;\nconst TABLE_CELL_GAUGE_DISPLAY_MODES_TO_DISPLAY_MODES: Record<TableCellGaugeDisplayModes, BarGaugeDisplayMode> = {\n [TableCellDisplayMode.BasicGauge]: BarGaugeDisplayMode.Basic,\n [TableCellDisplayMode.GradientGauge]: BarGaugeDisplayMode.Gradient,\n [TableCellDisplayMode.LcdGauge]: BarGaugeDisplayMode.Lcd,\n};\n\ntype TableCellColorBackgroundDisplayModes =\n | TableCellDisplayMode.ColorBackground\n | TableCellDisplayMode.ColorBackgroundSolid;\nconst TABLE_CELL_COLOR_BACKGROUND_DISPLAY_MODES_TO_DISPLAY_MODES: Record<\n TableCellColorBackgroundDisplayModes,\n TableCellBackgroundDisplayMode\n> = {\n [TableCellDisplayMode.ColorBackground]: TableCellBackgroundDisplayMode.Gradient,\n [TableCellDisplayMode.ColorBackgroundSolid]: TableCellBackgroundDisplayMode.Basic,\n};\n\n/* ---------------------------- Miscellaneous ---------------------------- */\n/**\n * Migrates table cell display mode to new object format.\n *\n * @param displayMode The display mode of the cell\n * @returns TableCellOptions object in the correct format\n * relative to the old display mode.\n */\nexport function migrateTableDisplayModeToCellOptions(displayMode: TableCellDisplayMode): TableCellOptions {\n switch (displayMode) {\n // In the case of the gauge we move to a different option\n case TableCellDisplayMode.BasicGauge:\n case TableCellDisplayMode.GradientGauge:\n case TableCellDisplayMode.LcdGauge:\n return {\n type: TableCellDisplayMode.Gauge,\n mode: TABLE_CELL_GAUGE_DISPLAY_MODES_TO_DISPLAY_MODES[displayMode],\n };\n // Also true in the case of the color background\n case TableCellDisplayMode.ColorBackground:\n case TableCellDisplayMode.ColorBackgroundSolid:\n return {\n type: TableCellDisplayMode.ColorBackground,\n mode: TABLE_CELL_COLOR_BACKGROUND_DISPLAY_MODES_TO_DISPLAY_MODES[displayMode],\n };\n // catching a nonsense case: `displayMode`: 'custom' should pre-date the CustomCell.\n // if it doesn't, we need to just nope out and return an auto cell.\n case TableCellDisplayMode.Custom:\n return {\n type: TableCellDisplayMode.Auto,\n };\n default:\n return {\n type: displayMode,\n };\n }\n}\n\n/**\n * @internal\n * Returns true if the DataFrame contains nested frames\n */\nexport const getIsNestedTable = (fields: Field[]): boolean =>\n fields.some(({ type }) => type === FieldType.nestedFrames);\n\n/**\n * @internal\n * Processes nested table rows\n */\nexport const processNestedTableRows = (\n rows: TableRow[],\n processParents: (parents: TableRow[]) => TableRow[]\n): TableRow[] => {\n // Separate parent and child rows\n // Array for parentRows: enables sorting and maintains order for iteration\n // Map for childRows: provides O(1) lookup by parent index when reconstructing the result\n const parentRows: TableRow[] = [];\n const childRows: Map<number, TableRow> = new Map();\n\n for (const row of rows) {\n if (Number(row.__depth) === 0) {\n parentRows.push(row);\n } else {\n childRows.set(Number(row.__index), row);\n }\n }\n\n // Process parent rows (filter or sort)\n const processedParents = processParents(parentRows);\n\n // Reconstruct the result\n const result: TableRow[] = [];\n processedParents.forEach((row) => {\n result.push(row);\n const childRow = childRows.get(Number(row.__index));\n if (childRow) {\n result.push(childRow);\n }\n });\n\n return result;\n};\n\n/**\n * @internal\n * returns the display name of a field\n */\nexport const getDisplayName = (field: Field): string => {\n return field.state?.displayName ?? field.name;\n};\n\n/**\n * @internal\n * returns only fields that are not nested tables and not explicitly hidden\n */\nexport function getVisibleFields(fields: Field[]): Field[] {\n return fields.filter((field) => field.type !== FieldType.nestedFrames && field.config.custom?.hidden !== true);\n}\n\n/**\n * @internal\n * returns a map of column types by display name\n */\nexport function getColumnTypes(fields: Field[]): ColumnTypes {\n return fields.reduce<ColumnTypes>((acc, field) => {\n switch (field.type) {\n case FieldType.nestedFrames:\n return { ...acc, ...getColumnTypes(field.values[0]?.[0]?.fields ?? []) };\n default:\n return { ...acc, [getDisplayName(field)]: field.type };\n }\n }, {});\n}\n\n/**\n * @internal\n * calculates the width of each field, with the following logic:\n * 1. manual sizing minWidth is hard-coded to 50px, we set this in RDG since it enforces the hard limit correctly\n * 2. if minWidth is configured in fieldConfig (or defaults to 150), it serves as the bottom of the auto-size clamp\n */\nexport function computeColWidths(fields: Field[], availWidth: number) {\n let autoCount = 0;\n let definedWidth = 0;\n\n return (\n fields\n // first pass to add up how many fields have pre-defined widths and what that width totals to.\n .map((field) => {\n const width: number = field.config.custom?.width ?? 0;\n\n if (width === 0) {\n autoCount++;\n } else {\n definedWidth += width;\n }\n\n return width;\n })\n // second pass once `autoCount` and `definedWidth` are known.\n .map(\n (width, i) =>\n width ||\n Math.max(fields[i].config.custom?.minWidth ?? COLUMN.DEFAULT_WIDTH, (availWidth - definedWidth) / autoCount)\n )\n );\n}\n\n/**\n * @internal\n * if applyToRow is true in any field, return a function that gets the row background color\n */\nexport function getApplyToRowBgFn(fields: Field[], theme: GrafanaTheme2): ((rowIndex: number) => CellColors) | void {\n for (const field of fields) {\n const cellOptions = getCellOptions(field);\n const fieldDisplay = field.display;\n if (\n fieldDisplay !== undefined &&\n cellOptions.type === TableCellDisplayMode.ColorBackground &&\n cellOptions.applyToRow === true\n ) {\n return (rowIndex: number) => getCellColors(theme, cellOptions, fieldDisplay(field.values[rowIndex]));\n }\n }\n}\n\n/** @internal */\nexport function withDataLinksActionsTooltip(field: Field, cellType: TableCellDisplayMode) {\n return (\n cellType !== TableCellDisplayMode.DataLinks &&\n cellType !== TableCellDisplayMode.Actions &&\n (field.config.links?.length ?? 0) + (field.config.actions?.length ?? 0) > 1\n );\n}\n"],"names":["compare"],"mappings":"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"}