UNPKG

@grafana/ui

Version:
1 lines 9.79 kB
{"version":3,"file":"PillCell.mjs","sources":["../../../../../../src/components/Table/TableNG/Cells/PillCell.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { Property } from 'csstype';\nimport { useMemo } from 'react';\n\nimport { GrafanaTheme2, isDataFrame, classicColors, colorManipulator, Field } from '@grafana/data';\nimport { TablePillCellOptions } from '@grafana/schema';\n\nimport { useStyles2 } from '../../../../themes/ThemeContext';\nimport { TableCellRendererProps } from '../types';\n\nconst DEFAULT_PILL_BG_COLOR = '#FF780A';\n\ninterface Pill {\n value: string;\n key: string;\n bgColor: string;\n color: string;\n}\n\nfunction createPills(pillValues: string[], cellOptions: TableCellRendererProps['cellOptions'], field: Field): Pill[] {\n return pillValues.map((pill, index) => {\n const bgColor = getPillColor(pill, cellOptions, field);\n const textColor = colorManipulator.getContrastRatio('#FFFFFF', bgColor) >= 4.5 ? '#FFFFFF' : '#000000';\n return {\n value: pill,\n key: `${pill}-${index}`,\n bgColor,\n color: textColor,\n };\n });\n}\n\nexport function PillCell({ value, field, justifyContent, cellOptions }: TableCellRendererProps) {\n const styles = useStyles2(getStyles, justifyContent);\n\n const pills: Pill[] = useMemo(() => {\n const pillValues = inferPills(value);\n return createPills(pillValues, cellOptions, field);\n }, [value, cellOptions, field]);\n\n if (pills.length === 0) {\n return <div className={styles.cell}>-</div>;\n }\n\n return (\n <div className={styles.cell}>\n <div className={styles.pillsContainer}>\n {pills.map((pill) => (\n <span\n key={pill.key}\n className={styles.pill}\n style={{\n backgroundColor: pill.bgColor,\n color: pill.color,\n }}\n >\n {pill.value}\n </span>\n ))}\n </div>\n </div>\n );\n}\n\nexport function inferPills(value: unknown): string[] {\n if (!value) {\n return [];\n }\n\n // Handle DataFrame - not supported for pills\n if (isDataFrame(value)) {\n return [];\n }\n\n // Handle different value types\n const stringValue = String(value);\n\n // Try to parse as JSON first\n try {\n const parsed = JSON.parse(stringValue);\n if (Array.isArray(parsed)) {\n // JSON array of strings\n return parsed\n .filter((item) => item != null && item !== '')\n .map(String)\n .map((text) => text.trim())\n .filter((item) => item !== '');\n }\n } catch {\n // Not valid JSON, continue with other parsing\n }\n\n // Handle CSV string\n if (stringValue.includes(',')) {\n return stringValue\n .split(',')\n .map((text) => text.trim())\n .filter((item) => item !== '');\n }\n\n // Single value - strip quotes\n return [stringValue.replace(/[\"'`]/g, '').trim()];\n}\n\nfunction isPillCellOptions(cellOptions: TableCellRendererProps['cellOptions']): cellOptions is TablePillCellOptions {\n return cellOptions?.type === 'pill';\n}\n\nfunction getPillColor(pill: string, cellOptions: TableCellRendererProps['cellOptions'], field: Field): string {\n if (!isPillCellOptions(cellOptions)) {\n return getDeterministicColor(pill);\n }\n\n const colorMode = cellOptions.colorMode || 'auto';\n\n // Fixed color mode (highest priority)\n if (colorMode === 'fixed' && cellOptions.color) {\n return cellOptions.color;\n }\n\n // Mapped color mode - use field's value mappings\n if (colorMode === 'mapped') {\n // Check if field has value mappings\n if (field.config.mappings && field.config.mappings.length > 0) {\n // Use the field's display processor to get the mapped value\n const displayValue = field.display!(pill);\n if (displayValue.color) {\n return displayValue.color;\n }\n }\n // Fallback to default color for unmapped values\n return cellOptions.color || DEFAULT_PILL_BG_COLOR;\n }\n\n // Auto mode - deterministic color assignment based on string hash\n if (colorMode === 'auto') {\n return getDeterministicColor(pill);\n }\n\n // Default color for unknown values or fallback\n return DEFAULT_PILL_BG_COLOR;\n}\n\nfunction getDeterministicColor(text: string): string {\n // Create a simple hash of the string to get consistent colors\n let hash = 0;\n for (let i = 0; i < text.length; i++) {\n const char = text.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32-bit integer\n }\n\n // Use absolute value and modulo to get a consistent index\n const colorValues = Object.values(classicColors);\n const index = Math.abs(hash) % colorValues.length;\n\n return colorValues[index];\n}\n\nconst getStyles = (theme: GrafanaTheme2, justifyContent: Property.JustifyContent | undefined) => ({\n cell: css({\n display: 'flex',\n justifyContent: justifyContent || 'flex-start',\n alignItems: 'center',\n height: '100%',\n padding: theme.spacing(0.5),\n }),\n pillsContainer: css({\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n maxWidth: '100%',\n }),\n pill: css({\n display: 'inline-block',\n padding: theme.spacing(0.25, 0.75),\n borderRadius: theme.shape.radius.default,\n fontSize: theme.typography.bodySmall.fontSize,\n lineHeight: theme.typography.bodySmall.lineHeight,\n fontWeight: theme.typography.fontWeightMedium,\n whiteSpace: 'nowrap',\n textAlign: 'center',\n minWidth: 'fit-content',\n }),\n});\n"],"names":[],"mappings":"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"}