UNPKG

@grafana/ui

Version:
1 lines • 43.6 kB
{"version":3,"file":"utils.mjs","sources":["../../../../src/components/Table/utils.ts"],"sourcesContent":["import { Property } from 'csstype';\nimport { clone, sampleSize } from 'lodash';\nimport memoize from 'micro-memoize';\nimport { HeaderGroup, Row } from 'react-table';\nimport tinycolor from 'tinycolor2';\n\nimport {\n ActionModel,\n DataFrame,\n DisplayValue,\n DisplayValueAlignmentFactors,\n Field,\n FieldConfigSource,\n fieldReducers,\n FieldType,\n formattedValueToString,\n getDisplayProcessor,\n getFieldDisplayName,\n GrafanaTheme2,\n isDataFrame,\n isDataFrameWithValue,\n isTimeSeriesFrame,\n LinkModel,\n reduceField,\n SelectableValue,\n} from '@grafana/data';\nimport {\n BarGaugeDisplayMode,\n TableAutoCellOptions,\n TableCellBackgroundDisplayMode,\n TableCellDisplayMode,\n} from '@grafana/schema';\n\nimport { getTextColorForAlphaBackground } from '../../utils/colors';\n\nimport { ActionsCell } from './ActionsCell';\nimport { BarGaugeCell } from './Cells/BarGaugeCell';\nimport { DataLinksCell } from './Cells/DataLinksCell';\nimport { DefaultCell } from './Cells/DefaultCell';\nimport { GeoCell } from './Cells/GeoCell';\nimport { ImageCell } from './Cells/ImageCell';\nimport { JSONViewCell } from './Cells/JSONViewCell';\nimport { SparklineCell } from './Cells/SparklineCell';\nimport { getFooterValue } from './TableRT/FooterRow';\nimport { RowExpander } from './TableRT/RowExpander';\nimport {\n CellColors,\n CellComponent,\n FooterItem,\n GrafanaTableColumn,\n TableCellOptions,\n TableFieldOptions,\n TableFooterCalc,\n} from './types';\n\nexport const EXPANDER_WIDTH = 50;\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: TableFieldOptions = 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\nexport function getColumns(\n data: DataFrame,\n availableWidth: number,\n columnMinWidth: number,\n expander: boolean,\n footerValues?: FooterItem[],\n isCountRowsSet?: boolean\n): GrafanaTableColumn[] {\n const columns: GrafanaTableColumn[] = [];\n let fieldCountWithoutWidth = 0;\n\n if (expander) {\n columns.push({\n // Make an expander cell\n Header: () => null, // No header\n id: 'expander', // It needs an ID\n // @ts-expect-error\n // TODO fix type error here\n Cell: RowExpander,\n width: EXPANDER_WIDTH,\n minWidth: EXPANDER_WIDTH,\n filter: (_rows: Row[], _id: string, _filterValues?: SelectableValue[]) => {\n return [];\n },\n justifyContent: 'left',\n field: data.fields[0],\n sortType: 'basic',\n });\n\n availableWidth -= EXPANDER_WIDTH;\n }\n\n for (const [fieldIndex, field] of data.fields.entries()) {\n const fieldTableOptions: TableFieldOptions = field.config.custom || {};\n if (fieldTableOptions.hidden || field.type === FieldType.nestedFrames) {\n continue;\n }\n\n if (fieldTableOptions.width) {\n availableWidth -= fieldTableOptions.width;\n } else {\n fieldCountWithoutWidth++;\n }\n\n const selectSortType = (type: FieldType) => {\n switch (type) {\n case FieldType.number:\n case FieldType.frame:\n return 'number';\n case FieldType.time:\n return 'basic';\n default:\n return 'alphanumeric-insensitive';\n }\n };\n\n const Cell = getCellComponent(fieldTableOptions.cellOptions?.type, field);\n columns.push({\n // @ts-expect-error\n // TODO fix type error here\n Cell,\n id: fieldIndex.toString(),\n field: field,\n Header: fieldTableOptions.hideHeader ? '' : getFieldDisplayName(field, data),\n accessor: (_row, i) => field.values[i],\n sortType: selectSortType(field.type),\n width: fieldTableOptions.width,\n minWidth: fieldTableOptions.minWidth ?? columnMinWidth,\n filter: memoize(filterByValue(field)),\n justifyContent: getTextAlign(field),\n Footer: getFooterValue(fieldIndex, footerValues, isCountRowsSet),\n });\n }\n\n // set columns that are at minimum width\n let sharedWidth = availableWidth / fieldCountWithoutWidth;\n for (let i = fieldCountWithoutWidth; i > 0; i--) {\n for (const column of columns) {\n if (!column.width && column.minWidth > sharedWidth) {\n column.width = column.minWidth;\n availableWidth -= column.width;\n fieldCountWithoutWidth -= 1;\n sharedWidth = availableWidth / fieldCountWithoutWidth;\n }\n }\n }\n\n // divide up the rest of the space\n for (const column of columns) {\n if (!column.width) {\n column.width = sharedWidth;\n }\n column.minWidth = 50;\n }\n\n return columns;\n}\n\nexport function getCellComponent(displayMode: TableCellDisplayMode, field: Field): CellComponent {\n switch (displayMode) {\n case TableCellDisplayMode.Custom:\n case TableCellDisplayMode.ColorText:\n case TableCellDisplayMode.ColorBackground:\n return DefaultCell;\n case TableCellDisplayMode.Image:\n return ImageCell;\n case TableCellDisplayMode.Gauge:\n return BarGaugeCell;\n case TableCellDisplayMode.Sparkline:\n return SparklineCell;\n case TableCellDisplayMode.JSONView:\n return JSONViewCell;\n case TableCellDisplayMode.DataLinks:\n return DataLinksCell;\n case TableCellDisplayMode.Actions:\n return ActionsCell;\n case TableCellDisplayMode.Pill:\n return DefaultCell; // Legacy table doesn't support pill cells, fallback to default\n }\n\n if (field.type === FieldType.geo) {\n return GeoCell;\n }\n\n if (field.type === FieldType.frame) {\n const firstValue = field.values[0];\n if (isDataFrame(firstValue) && isTimeSeriesFrame(firstValue)) {\n return SparklineCell;\n }\n\n return JSONViewCell;\n }\n\n // Default or Auto\n if (field.type === FieldType.other) {\n return JSONViewCell;\n }\n\n return DefaultCell;\n}\n\nexport function filterByValue(field?: Field) {\n return function (rows: Row[], id: string, filterValues?: SelectableValue[]) {\n if (rows.length === 0) {\n return rows;\n }\n\n if (!filterValues) {\n return rows;\n }\n\n if (!field) {\n return rows;\n }\n\n return rows.filter((row) => {\n if (!row.values.hasOwnProperty(id)) {\n return false;\n }\n const value = rowToFieldValue(row, field);\n return filterValues.find((filter) => filter.value === value) !== undefined;\n });\n };\n}\n\nexport function calculateUniqueFieldValues(rows: any[], field?: Field) {\n if (!field || rows.length === 0) {\n return {};\n }\n\n const set: Record<string, string> = {};\n\n for (let index = 0; index < rows.length; index++) {\n const value = rowToFieldValue(rows[index], field);\n set[value || '(Blanks)'] = value;\n }\n\n return set;\n}\n\nexport function rowToFieldValue(row: any, field?: Field): string {\n if (!field || !row) {\n return '';\n }\n\n const fieldValue = field.values[row.index];\n const displayValue = field.display ? field.display(fieldValue) : fieldValue;\n const value = field.display ? formattedValueToString(displayValue) : displayValue;\n\n return value;\n}\n\nexport function valuesToOptions(unique: Record<string, unknown>): SelectableValue[] {\n return Object.keys(unique)\n .reduce<SelectableValue[]>((all, key) => all.concat({ value: unique[key], label: key }), [])\n .sort(sortOptions);\n}\n\nexport function sortOptions(a: SelectableValue, b: SelectableValue): number {\n if (a.label === undefined && b.label === undefined) {\n return 0;\n }\n\n if (a.label === undefined && b.label !== undefined) {\n return -1;\n }\n\n if (a.label !== undefined && b.label === undefined) {\n return 1;\n }\n\n if (a.label! < b.label!) {\n return -1;\n }\n\n if (a.label! > b.label!) {\n return 1;\n }\n\n return 0;\n}\n\nexport function getFilteredOptions(options: SelectableValue[], filterValues?: SelectableValue[]): SelectableValue[] {\n if (!filterValues) {\n return [];\n }\n\n return options.filter((option) => filterValues.some((filtered) => filtered.value === option.value));\n}\n\nexport function sortCaseInsensitive(a: Row, b: Row, id: string) {\n return String(a.values[id]).localeCompare(String(b.values[id]), undefined, { sensitivity: 'base' });\n}\n\n// sortNumber needs to have great performance as it is called a lot\nexport function sortNumber(rowA: Row, rowB: Row, id: string) {\n const a = toNumber(rowA.values[id]);\n const b = toNumber(rowB.values[id]);\n return a === b ? 0 : a > b ? 1 : -1;\n}\n\nfunction toNumber(value: any): number {\n if (isDataFrameWithValue(value)) {\n return value.value ?? Number.NEGATIVE_INFINITY;\n }\n\n if (value === null || value === undefined || value === '' || isNaN(value)) {\n return Number.NEGATIVE_INFINITY;\n }\n\n if (typeof value === 'number') {\n return value;\n }\n\n return Number(value);\n}\n\nexport function getFooterItems(\n filterFields: Array<{ id: string; field?: Field } | undefined>,\n values: any[number],\n options: TableFooterCalc,\n theme2: GrafanaTheme2\n): FooterItem[] {\n /*\n The FooterItems[] are calculated using both the `headerGroups[0].headers`\n (filterFields) and `rows` (values) destructured from the useTable() hook.\n This cacluation is based on the data from each index in `filterFields`\n array as well as the corresponding index in the `values` array.\n When the user hides a column through an override, the getColumns()\n hook is invoked, removes said hidden column, sends the updated column\n data to the useTable() hook, which then builds `headerGroups[0].headers`\n without the hidden column. However, it doesn't remove the hidden column\n from the `row` data, instead it substututes the hidden column row data\n with an `undefined` value. Therefore, the `row` array length never changes,\n despite the `headerGroups[0].headers` length changing at every column removal.\n This makes all footer reduce calculations AFTER the first hidden column\n in the `headerGroups[0].headers` break, since the indexing of both\n arrays is no longer in parity.\n\n So, here we simply recursively test for the \"hidden\" columns\n from `headerGroups[0].headers`. Each column has an ID property that corresponds\n to its own index, therefore if (`filterField.id` !== `String(index)`),\n we know there is one or more hidden columns; at which point we update\n the index with an ersatz placeholder with just an `id` property.\n */\n addMissingColumnIndex(filterFields);\n\n return filterFields.map((data, i) => {\n // Then test for numerical data - this will filter out placeholder `filterFields` as well.\n if (data?.field?.type !== FieldType.number) {\n // Show the reducer in the first column\n if (i === 0 && options.reducer && options.reducer.length > 0) {\n const reducer = fieldReducers.get(options.reducer[0]);\n return reducer.name;\n }\n // Render an <EmptyCell />.\n return undefined;\n }\n\n let newField = clone(data.field);\n newField.values = values[data.id];\n newField.state = undefined;\n\n data.field = newField;\n\n if (options.fields && options.fields.length > 0) {\n const f = options.fields.find((f) => f === data?.field?.name);\n if (f) {\n return getFormattedValue(data.field, options.reducer, theme2);\n }\n return undefined;\n }\n return getFormattedValue(data.field, options.reducer || [], theme2);\n });\n}\n\nfunction getFormattedValue(field: Field, reducer: string[], theme: GrafanaTheme2) {\n // If we don't have anything to return then we display nothing\n const calc = reducer[0];\n if (calc === undefined) {\n return '';\n }\n\n // Calculate the reduction\n const format = field.display ?? getDisplayProcessor({ field, theme });\n const fieldCalcValue = reduceField({ field, reducers: reducer })[calc];\n\n // If the reducer preserves units then format the\n // end value with the field display processor\n const reducerInfo = fieldReducers.get(calc);\n if (reducerInfo.preservesUnits) {\n return formattedValueToString(format(fieldCalcValue));\n }\n\n // Otherwise we simply return the formatted string\n return formattedValueToString({ text: fieldCalcValue });\n}\n\n// This strips the raw vales from the `rows` object.\nexport function createFooterCalculationValues(rows: Row[]): any[number] {\n const values: any[number] = [];\n\n for (const key in rows) {\n for (const [valKey, val] of Object.entries(rows[key].values)) {\n if (values[valKey] === undefined) {\n values[valKey] = [];\n }\n values[valKey].push(val);\n }\n }\n\n return values;\n}\n\nconst defaultCellOptions: TableAutoCellOptions = { type: TableCellDisplayMode.Auto };\n\nexport function getCellOptions(field: Field): TableCellOptions {\n if (field.config.custom?.displayMode) {\n return migrateTableDisplayModeToCellOptions(field.config.custom?.displayMode);\n }\n\n if (!field.config.custom?.cellOptions) {\n return defaultCellOptions;\n }\n\n return field.config.custom.cellOptions;\n}\n\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 'basic':\n case 'gradient-gauge':\n case 'lcd-gauge':\n let gaugeMode = BarGaugeDisplayMode.Basic;\n\n if (displayMode === 'gradient-gauge') {\n gaugeMode = BarGaugeDisplayMode.Gradient;\n } else if (displayMode === 'lcd-gauge') {\n gaugeMode = BarGaugeDisplayMode.Lcd;\n }\n\n return {\n type: TableCellDisplayMode.Gauge,\n mode: gaugeMode,\n };\n // Also true in the case of the color background\n case 'color-background':\n case 'color-background-solid':\n let mode = TableCellBackgroundDisplayMode.Basic;\n\n // Set the new mode field, somewhat confusingly the\n // color-background mode is for gradient display\n if (displayMode === 'color-background') {\n mode = TableCellBackgroundDisplayMode.Gradient;\n }\n\n return {\n type: TableCellDisplayMode.ColorBackground,\n mode: mode,\n };\n default:\n return {\n // @ts-ignore\n type: displayMode,\n };\n }\n}\n\n/**\n * This recurses through an array of `filterFields` (Array<{ id: string; field?: Field } | undefined>)\n * and adds back the missing indecies that are removed due to hiding a column through an panel override.\n * This is necessary to create Array.length parity between the `filterFields` array and the `values` array (any[number]),\n * since the footer value calculations are based on the corresponding index values of both arrays.\n *\n * @remarks\n * This function uses the splice() method, and therefore mutates the array.\n *\n * @param columns - An array of `filterFields` (Array<{ id: string; field?: Field } | undefined>).\n * @returns void; this function returns nothing; it only mutates values as a side effect.\n */\nfunction addMissingColumnIndex(columns: Array<{ id: string; field?: Field } | undefined>): void {\n const missingIndex = columns.findIndex((field, index) => field?.id !== String(index));\n\n // Base case\n if (missingIndex === -1 || columns[missingIndex]?.id === 'expander') {\n return;\n }\n\n // Splice in missing column\n columns.splice(missingIndex, 0, { id: String(missingIndex) });\n\n // Recurse\n addMissingColumnIndex(columns);\n}\n\n/**\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]);\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// since the conversion from timeseries panel crosshair to time is pixel based, we need\n// to set a threshold where the table row highlights when the crosshair is hovered over a certain point\n// because multiple pixels (converted to times) may represent the same point/row in table\nexport function isPointTimeValAroundTableTimeVal(pointTime: number, rowTime: number, threshold: number) {\n return Math.abs(Math.floor(pointTime) - rowTime) < threshold;\n}\n\n// calculate the threshold for which we consider a point in a chart\n// to match a row in a table based on a time value\nexport function calculateAroundPointThreshold(timeField: Field): number {\n let max = -Number.MAX_VALUE;\n let min = Number.MAX_VALUE;\n\n if (timeField.values.length < 2) {\n return 0;\n }\n\n for (let i = 0; i < timeField.values.length; i++) {\n const value = timeField.values[i];\n if (value > max) {\n max = value;\n }\n if (value < min) {\n min = value;\n }\n }\n\n return (max - min) / timeField.values.length;\n}\n\n/**\n * Retrieve colors for a table cell (or table row).\n *\n * @param tableStyles\n * Styles for the table\n * @param cellOptions\n * Table cell configuration options\n * @param displayValue\n * The value that will be displayed\n * @returns CellColors\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).setAlpha(1).toRgbString();\n } else if (mode === TableCellBackgroundDisplayMode.Gradient) {\n const hoverColor = tinycolor(displayValue.color).setAlpha(1).toRgbString();\n const bgColor2 = tinycolor(displayValue.color)\n .darken(10 * darkeningFactor)\n .spin(5);\n textColor = getTextColorForAlphaBackground(displayValue.color!, theme.isDark);\n bgColor = `linear-gradient(120deg, ${bgColor2.toRgbString()}, ${displayValue.color})`;\n bgHoverColor = `linear-gradient(120deg, ${bgColor2.setAlpha(1).toRgbString()}, ${hoverColor})`;\n }\n }\n\n return { textColor, bgColor, bgHoverColor };\n}\n\n/**\n * Calculate an estimated bounding box for a block\n * of text using an offscreen canvas.\n */\nexport function guessTextBoundingBox(\n text: string,\n headerGroup: HeaderGroup,\n osContext: OffscreenCanvasRenderingContext2D | null,\n lineHeight: number,\n defaultRowHeight: number,\n padding = 0\n) {\n const width = Number(headerGroup?.width ?? 300);\n const LINE_SCALE_FACTOR = 1.17;\n const LOW_LINE_PAD = 42;\n const PADDING = padding * 2;\n\n if (osContext !== null && typeof text === 'string') {\n const words = text.split(/\\s/);\n const lines = [];\n let currentLine = '';\n let wordCount = 0;\n let extraLines = 0;\n\n // Let's just wrap the lines and see how well the measurement works\n for (let i = 0; i < words.length; i++) {\n const currentWord = words[i];\n let lineWidth = osContext.measureText(currentLine + ' ' + currentWord).width;\n\n if (lineWidth < width - PADDING) {\n currentLine += ' ' + currentWord;\n wordCount++;\n } else {\n lines.push({\n width: lineWidth,\n line: currentLine,\n });\n\n currentLine = currentWord;\n wordCount = 0;\n }\n }\n\n // We can have extra long strings, for these\n // we estimate if it overshoots the line by\n // at least one other line\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].width > width) {\n let extra = Math.floor(lines[i].width / width) - 1;\n extraLines += extra;\n }\n }\n\n // Estimated height would be lines multiplied\n // by the line height\n let lineNumber = lines.length + extraLines;\n let height = 38;\n if (lineNumber > 5) {\n height = lineNumber * lineHeight * LINE_SCALE_FACTOR;\n } else {\n height = lineNumber * lineHeight + LOW_LINE_PAD;\n }\n height += PADDING;\n\n return { width, height };\n }\n\n return { width, height: defaultRowHeight };\n}\n\n/**\n * A function to guess at which field has the longest text.\n * To do this we either select a single record if there aren't many records\n * or we select records at random and sample their size.\n */\nexport function guessLongestField(fieldConfig: FieldConfigSource, data: DataFrame) {\n let longestField = undefined;\n const SAMPLE_SIZE = 3;\n\n // If the default field option is set to allow text wrapping\n // we determine the field to wrap text with here and then\n // pass it to the RowsList\n if (fieldConfig.defaults.custom?.cellOptions?.wrapText) {\n const stringFields = data.fields.filter((field: Field) => field.type === FieldType.string);\n\n if (stringFields.length >= 1 && stringFields[0].values.length > 0) {\n const numValues = stringFields[0].values.length;\n let longestLength = 0;\n\n // If we have less than 30 values we assume that the first\n // non-null record is representative of the overall data\n if (numValues <= 30) {\n for (const field of stringFields) {\n const fieldLength = field.values.find((v) => v != null)?.length ?? 0;\n if (fieldLength > longestLength) {\n longestLength = fieldLength;\n longestField = field;\n }\n }\n }\n // Otherwise we randomly sample SAMPLE_SIZE values and take\n // the mean length\n else {\n for (const field of stringFields) {\n // This could result in duplicate values but\n // that should be fairly unlikely. This could potentially\n // be improved using a Set datastructure but\n // going to leave that one as an exercise for\n // the reader to contemplate and possibly code\n const vals = sampleSize(field.values, SAMPLE_SIZE);\n const meanLength = (vals[0]?.length + vals[1]?.length + vals[2]?.length) / 3;\n\n if (meanLength > longestLength) {\n longestLength = meanLength;\n longestField = field;\n }\n }\n }\n }\n }\n\n return longestField;\n}\n\nexport interface DataLinksActionsTooltipState {\n coords: DataLinksActionsTooltipCoords;\n links?: LinkModel[];\n actions?: ActionModel[];\n}\n\nexport interface DataLinksActionsTooltipCoords {\n clientX: number;\n clientY: number;\n}\n\nexport const getDataLinksActionsTooltipUtils = (links: LinkModel[], actions?: ActionModel[]) => {\n const hasMultipleLinksOrActions = links.length > 1 || Boolean(actions?.length);\n const shouldShowLink = links.length === 1 && !Boolean(actions?.length);\n\n return { shouldShowLink, hasMultipleLinksOrActions };\n};\n\nconst shouldTriggerTooltip = (event: React.MouseEvent<HTMLElement>): boolean => {\n return event.target === event.currentTarget;\n};\n\n/**\n * Creates an onClick handler for table cells that only triggers tooltip when clicking directly on the cell\n * @param setTooltipCoords - function to set tooltip coordinates\n * @returns onClick handler\n */\nexport const tooltipOnClickHandler = (setTooltipCoords: (coords: DataLinksActionsTooltipCoords) => void) => {\n return (event: React.MouseEvent<HTMLElement>) => {\n if (shouldTriggerTooltip(event)) {\n const { clientX, clientY } = event;\n setTooltipCoords({ clientX, clientY });\n }\n };\n};\n"],"names":["f","_a"],"mappings":"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"}