@grafana/ui
Version:
Grafana Components Library
815 lines (810 loc) • 31 kB
JavaScript
import memoize from 'micro-memoize';
import tinycolor from 'tinycolor2';
import { varPreLine } from 'uwrap';
import { FieldType, formattedValueToString, isDataFrame } from '@grafana/data';
import { TableCellHeight, TableCellDisplayMode, TableCellBackgroundDisplayMode, BarGaugeDisplayMode } from '@grafana/schema';
import { getTextColorForAlphaBackground } from '../../../utils/colors.mjs';
import { TableCellInspectorMode } from '../TableCellInspector.mjs';
import '../geo/index.mjs';
import { inferPills } from './Cells/PillCell.mjs';
import { getCellRenderer, AutoCellRenderer, getAutoRendererDisplayMode } from './Cells/renderers.mjs';
import { TABLE, COLUMN } from './constants.mjs';
import { isGeometry } from '../geo/utils.mjs';
;
function getDefaultRowHeight(theme, fields, cellHeight) {
if (fields == null ? void 0 : fields.some((field) => {
var _a, _b, _c;
return (_c = (_b = (_a = field.config) == null ? void 0 : _a.custom) == null ? void 0 : _b.cellOptions) == null ? void 0 : _c.dynamicHeight;
})) {
return "min-content";
}
switch (cellHeight) {
case TableCellHeight.Sm:
return 36;
case TableCellHeight.Md:
return 42;
case TableCellHeight.Lg:
return TABLE.MAX_CELL_HEIGHT;
}
return TABLE.CELL_PADDING * 2 + theme.typography.fontSize * theme.typography.body.lineHeight;
}
function isCellInspectEnabled(field) {
var _a, _b, _c;
return (_c = (_b = (_a = field.config) == null ? void 0 : _a.custom) == null ? void 0 : _b.inspect) != null ? _c : false;
}
function shouldTextWrap(field) {
var _a;
return Boolean((_a = field.config.custom) == null ? void 0 : _a.wrapText);
}
function clampByMaxHeight(measurer, maxHeight = Infinity) {
return (value, width, field, rowIdx, lineHeight) => {
const rawHeight = measurer(value, width, field, rowIdx, lineHeight);
return Math.min(rawHeight, maxHeight);
};
}
function createTypographyContext(fontSize, fontFamily, letterSpacing = 0.15) {
const font = `${fontSize}px ${fontFamily}`;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
ctx.letterSpacing = `${letterSpacing}px`;
ctx.font = font;
const txt = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s. 1234567890 ALL CAPS TO HELP WITH MEASUREMENT.";
const txtWidth = ctx.measureText(txt).width;
const avgCharWidth = txtWidth / txt.length + letterSpacing;
const { count } = varPreLine(ctx);
return {
ctx,
fontFamily,
letterSpacing,
avgCharWidth,
estimateHeight: getTextHeightEstimator(avgCharWidth),
measureHeight: getTextHeightMeasurerFromUwrapCount(count)
};
}
function getTextHeightMeasurerFromUwrapCount(count) {
return (value, width, _field, _rowIdx, lineHeight) => {
if (value == null) {
return lineHeight;
}
const lines = count(String(value), width);
return lines * lineHeight;
};
}
function getTextHeightEstimator(avgCharWidth) {
return (value, width, _field, _rowIdx, lineHeight) => {
if (!value) {
return -1;
}
const strValue = String(value);
if (!spaceRegex.test(strValue)) {
return -1;
}
const charsPerLine = width / avgCharWidth;
const lines = Math.ceil(strValue.length / charsPerLine);
return lines * lineHeight;
};
}
function getDataLinksHeightMeasurer() {
const linksCountCache = {};
return (_value, _width, field, _rowIdx, lineHeight) => {
var _a, _b;
const cacheKey = getDisplayName(field);
if (linksCountCache[cacheKey] === void 0) {
let count = 0;
for (const l of (_b = (_a = field.config) == null ? void 0 : _a.links) != null ? _b : []) {
if (l.onClick || l.url) {
count += 1;
}
}
linksCountCache[cacheKey] = count;
}
return linksCountCache[cacheKey] * lineHeight;
};
}
const PILLS_FONT_SIZE = 12;
const PILLS_SPACING = 12;
const PILLS_GAP = 4;
function getPillCellHeightMeasurer(measureWidth) {
const widthCache = {};
return (value, width, _field, _rowIdx, lineHeight) => {
if (value == null) {
return 0;
}
const pillValues = inferPills(String(value));
if (pillValues.length === 0) {
return 0;
}
let lines = 0;
let currentLineUse = width;
for (const pillValue of pillValues) {
const strPill = String(pillValue);
let rawWidth = widthCache[strPill];
if (rawWidth === void 0) {
rawWidth = measureWidth(strPill);
widthCache[strPill] = rawWidth;
}
const pillWidth = rawWidth + PILLS_SPACING;
if (currentLineUse + pillWidth + PILLS_GAP > width) {
lines++;
currentLineUse = pillWidth;
} else {
currentLineUse += pillWidth + PILLS_GAP;
}
}
return lines * lineHeight + (lines - 1) * PILLS_GAP;
};
}
function buildHeaderHeightMeasurers(fields, typographyCtx) {
const wrappedColIdxs = fields.reduce((acc, field, idx) => {
var _a, _b;
if ((_b = (_a = field.config) == null ? void 0 : _a.custom) == null ? void 0 : _b.wrapHeaderText) {
acc.push(idx);
}
return acc;
}, []);
if (wrappedColIdxs.length === 0) {
return void 0;
}
return [{ measure: typographyCtx.measureHeight, fieldIdxs: wrappedColIdxs }];
}
const spaceRegex = /[\s-]/;
function buildCellHeightMeasurers(fields, typographyCtx, maxHeight) {
const result = {};
let wrappedFields = 0;
const measurerFactory = {
// for string fields, we estimate the length of a line using `avgCharWidth` to limit expensive calls `count`.
[TableCellDisplayMode.Auto]: () => [typographyCtx.measureHeight, typographyCtx.estimateHeight],
[TableCellDisplayMode.DataLinks]: () => [getDataLinksHeightMeasurer(), void 0],
// pills use a different font size, so they require their own typography context.
[TableCellDisplayMode.Pill]: () => {
const pillTypographyCtx = createTypographyContext(
PILLS_FONT_SIZE,
typographyCtx.fontFamily,
typographyCtx.letterSpacing
);
return [
getPillCellHeightMeasurer((value) => pillTypographyCtx.ctx.measureText(value).width),
getPillCellHeightMeasurer((value) => value.length * pillTypographyCtx.avgCharWidth)
];
}
};
const setupMeasurerForIdx = (measurerFactoryKey, fieldIdx) => {
if (!result[measurerFactoryKey]) {
const [measure, estimate] = measurerFactory[measurerFactoryKey]();
result[measurerFactoryKey] = {
measure: clampByMaxHeight(measure, maxHeight),
estimate: estimate != null ? clampByMaxHeight(estimate, maxHeight) : void 0,
fieldIdxs: []
};
}
result[measurerFactoryKey].fieldIdxs.push(fieldIdx);
};
for (let fieldIdx = 0; fieldIdx < fields.length; fieldIdx++) {
const field = fields[fieldIdx];
if (shouldTextWrap(field)) {
wrappedFields++;
const cellType = getCellOptions(field).type;
if (cellType === TableCellDisplayMode.DataLinks) {
setupMeasurerForIdx(TableCellDisplayMode.DataLinks, fieldIdx);
} else if (cellType === TableCellDisplayMode.Pill) {
setupMeasurerForIdx(TableCellDisplayMode.Pill, fieldIdx);
} else if (getCellRenderer(field, getCellOptions(field)) === AutoCellRenderer) {
setupMeasurerForIdx(TableCellDisplayMode.Auto, fieldIdx);
} else {
wrappedFields--;
}
}
}
if (wrappedFields === 0) {
return void 0;
}
return Object.values(result);
}
const SINGLE_LINE_ESTIMATE_THRESHOLD = 18.5;
function getRowHeight(fields, row, columnWidths, defaultHeight, measurers, lineHeight = TABLE.LINE_HEIGHT, verticalPadding = TABLE.CELL_PADDING * 2) {
if (!(measurers == null ? void 0 : measurers.length)) {
return defaultHeight;
}
let maxHeight = -1;
let maxValue = "";
let maxWidth = 0;
let maxField;
let preciseMeasurer;
for (const { estimate, measure, fieldIdxs } of measurers) {
const measurer = estimate != null ? estimate : measure;
const isEstimating = estimate !== void 0;
for (const fieldIdx of fieldIdxs) {
const field = fields[fieldIdx];
const displayName = getDisplayName(field);
const cellValueRaw = row.__index === -1 ? displayName : row[displayName];
if (cellValueRaw != null) {
const cellValueForMeasuring = field.type !== FieldType.string && row.__index !== -1 && field.display != null ? formattedValueToString(field.display(cellValueRaw)) : cellValueRaw;
const colWidth = columnWidths[fieldIdx];
const estimatedHeight = measurer(cellValueForMeasuring, colWidth, field, row.__index, lineHeight);
if (estimatedHeight > maxHeight) {
maxHeight = estimatedHeight;
maxValue = cellValueForMeasuring;
maxWidth = colWidth;
maxField = field;
preciseMeasurer = isEstimating ? measure : void 0;
}
}
}
}
if (maxField === void 0 || maxHeight < SINGLE_LINE_ESTIMATE_THRESHOLD) {
return defaultHeight;
}
if (preciseMeasurer !== void 0) {
maxHeight = preciseMeasurer(maxValue, maxWidth, maxField, row.__index, lineHeight);
}
return Math.max(maxHeight + verticalPadding, defaultHeight);
}
function shouldTextOverflow(field) {
const cellOptions = getCellOptions(field);
const eligibleCellType = (
// Tech debt: Technically image cells are of type string, which is misleading (kinda?)
// so we need to ensurefield.type === FieldType.string we don't apply overflow hover states for type image
field.type === FieldType.string && cellOptions.type !== TableCellDisplayMode.Image || // regardless of the underlying cell type, data links cells have text overflow.
cellOptions.type === TableCellDisplayMode.DataLinks
);
return eligibleCellType && !shouldTextWrap(field) && !isCellInspectEnabled(field);
}
const TEXT_CELL_TYPES = /* @__PURE__ */ new Set([
TableCellDisplayMode.Auto,
TableCellDisplayMode.ColorText,
TableCellDisplayMode.ColorBackground
]);
function getAlignment(field) {
var _a;
const align = (_a = field.config.custom) == null ? void 0 : _a.align;
if (!align || align === "auto") {
if (TEXT_CELL_TYPES.has(getCellOptions(field).type) && field.type === FieldType.number) {
return "right";
}
return "left";
}
return align;
}
function getJustifyContent(textAlign) {
return textAlign === "center" ? "center" : textAlign === "right" ? "flex-end" : "flex-start";
}
const DEFAULT_CELL_OPTIONS = { type: TableCellDisplayMode.Auto };
function getCellOptions(field) {
var _a, _b, _c, _d;
if ((_a = field.config.custom) == null ? void 0 : _a.displayMode) {
return migrateTableDisplayModeToCellOptions((_b = field.config.custom) == null ? void 0 : _b.displayMode);
}
return (_d = (_c = field.config.custom) == null ? void 0 : _c.cellOptions) != null ? _d : DEFAULT_CELL_OPTIONS;
}
function getAlignmentFactor(field, displayValue, rowIndex) {
var _a, _b, _c;
let alignmentFactor = (_a = field.state) == null ? void 0 : _a.alignmentFactors;
if (alignmentFactor) {
if (formattedValueToString(alignmentFactor).length < formattedValueToString(displayValue).length) {
alignmentFactor = { ...displayValue };
field.state.alignmentFactors = alignmentFactor;
}
return alignmentFactor;
} else {
alignmentFactor = { ...displayValue };
const maxIndex = Math.min(field.values.length, rowIndex + 1e3);
for (let i = rowIndex + 1; i < maxIndex; i++) {
const nextDisplayValue = (_c = (_b = field.display) == null ? void 0 : _b.call(field, field.values[i])) != null ? _c : field.values[i];
if (formattedValueToString(alignmentFactor).length > formattedValueToString(nextDisplayValue).length) {
alignmentFactor.text = displayValue.text;
}
}
if (field.state) {
field.state.alignmentFactors = alignmentFactor;
} else {
field.state = { alignmentFactors: alignmentFactor };
}
return alignmentFactor;
}
}
const CELL_COLOR_DARKENING_MULTIPLIER = 10;
const CELL_GRADIENT_HUE_ROTATION_DEGREES = 5;
function getCellColorInlineStylesFactory(theme) {
const bgCellTextColor = memoize((color) => getTextColorForAlphaBackground(color, theme.isDark), {
maxSize: 1e3
});
const darkeningFactor = theme.isDark ? 1 : -0.7;
const gradientBg = memoize(
(color) => tinycolor(color).darken(CELL_COLOR_DARKENING_MULTIPLIER * darkeningFactor).spin(CELL_GRADIENT_HUE_ROTATION_DEGREES).toRgbString(),
{ maxSize: 1e3 }
);
const isTransparent = memoize(
(color) => {
if (color[0] === "#") {
return color.length === 9 && color.endsWith("00");
}
return tinycolor(color).getAlpha() === 0;
},
{ maxSize: 1e3 }
);
return (cellOptions, displayValue, hasApplyToRow) => {
var _a;
const result = {};
const displayValueColor = displayValue.color;
if (!displayValueColor) {
return result;
}
if (cellOptions.type === TableCellDisplayMode.ColorText) {
result.color = displayValueColor;
} else if (cellOptions.type === TableCellDisplayMode.ColorBackground) {
if (hasApplyToRow && isTransparent(displayValueColor)) {
return result;
}
const mode = (_a = cellOptions.mode) != null ? _a : TableCellBackgroundDisplayMode.Gradient;
result.color = bgCellTextColor(displayValueColor);
result.background = mode === TableCellBackgroundDisplayMode.Gradient ? `linear-gradient(120deg, ${gradientBg(displayValueColor)}, ${displayValueColor})` : displayValueColor;
}
return result;
};
}
const extractPixelValue = (spacing) => {
return typeof spacing === "number" ? spacing : parseFloat(spacing) || 0;
};
const getCellLinks = (field, rowIdx) => {
let links;
if (field.getLinks) {
links = field.getLinks({
valueRowIndex: rowIdx
});
}
if (!links) {
return;
}
for (let i = 0; i < (links == null ? void 0 : links.length); i++) {
if (links[i].onClick) {
const origOnClick = links[i].onClick;
links[i].onClick = (event) => {
if (!(event.ctrlKey || event.metaKey || event.shiftKey)) {
event.preventDefault();
origOnClick(event, {
field,
rowIndex: rowIdx
});
}
};
}
}
return links.filter((link) => link.href || link.onClick != null);
};
const processNestedTableRows = (rows, processParents) => {
const parentRows = [];
const childRows = /* @__PURE__ */ new Map();
for (const row of rows) {
if (row.__depth === 0) {
parentRows.push(row);
} else {
childRows.set(row.__index, row);
}
}
const processedParents = processParents(parentRows);
const result = [];
for (const row of processedParents) {
result.push(row);
const childRow = childRows.get(row.__index);
if (childRow) {
result.push(childRow);
}
}
return result;
};
function applySort(rows, fields, sortColumns, columnTypes, hasNestedFrames) {
if (sortColumns.length === 0) {
return rows;
}
const sortNanos = sortColumns.map(
(c) => {
var _a;
return (_a = fields.find((f) => f.type === FieldType.time && getDisplayName(f) === c.columnKey)) == null ? void 0 : _a.nanos;
}
);
const compareRows = (a, b) => {
let result = 0;
for (let i = 0; i < sortColumns.length; i++) {
const { columnKey, direction } = sortColumns[i];
const compare2 = getComparator(columnTypes[columnKey]);
const sortDir = direction === "ASC" ? 1 : -1;
result = sortDir * compare2(a[columnKey], b[columnKey]);
if (result === 0) {
const nanos = sortNanos[i];
if (nanos !== void 0) {
result = sortDir * (nanos[a.__index] - nanos[b.__index]);
}
}
if (result !== 0) {
break;
}
}
return result;
};
return hasNestedFrames ? processNestedTableRows(rows, (parents) => parents.sort(compareRows)) : [...rows].sort(compareRows);
}
function applyFilter(rows, filter, fields, hasNestedFrames, parentIndex) {
const isNested = parentIndex !== void 0;
const scopedRows = !isNested ? rows.filter((r) => r.__depth === 0) : rows;
const crossFilterOrder = Object.keys(filter).filter((key) => {
const entry = filter[key];
return !isNested ? entry.parentIndex == null : entry.parentIndex === parentIndex;
});
const crossFilterRows = {};
let crossFilterTailRows = scopedRows;
for (const filterKey of crossFilterOrder) {
const filterEntry = filter[filterKey];
crossFilterRows[filterKey] = crossFilterTailRows;
crossFilterTailRows = crossFilterTailRows.filter((row) => {
const field = fields.find((f) => getDisplayName(f) === filterEntry.displayName);
if (!field || !field.display) {
return true;
}
const displayedValue = formattedValueToString(field.display(row[filterEntry.displayName]));
return filterEntry.filteredSet.has(displayedValue);
});
}
let filteredRows = crossFilterTailRows;
if (hasNestedFrames) {
const tailSet = new Set(crossFilterTailRows);
filteredRows = processNestedTableRows(rows, (parents) => parents.filter((row) => tailSet.has(row)));
}
return { crossFilterOrder, crossFilterRows, crossFilterTailRows, filteredRows };
}
function compileFrameToRecordsV1(frame, nestedFramesFieldName) {
const hasNestedFrames = (nestedFramesFieldName != null ? nestedFramesFieldName : "").length > 0;
const fnBody = `
const values = frame.fields.map(f => f.values);
const hasNestedFrames = ${hasNestedFrames};
const frameLength = frame.length ?? values[0]?.length ?? 0;
const rows = Array(frameLength);
let rowCount = 0;
for (let i = 0; i < frameLength; i++) {
rows[rowCount] = {
__depth: 0,
__index: i,
${frame.fields.map((field, fieldIdx) => `${JSON.stringify(getDisplayName(field))}: values[${fieldIdx}][i]`).join(",")}
};
if (nestedRowIndex != null) {
rows[rowCount].__parentIndex = nestedRowIndex;
}
rowCount++;
if (hasNestedFrames) {
const childFrame = rows[rowCount-1][${JSON.stringify(nestedFramesFieldName)}];
if (childFrame) {
delete rows[rowCount - 1][${JSON.stringify(nestedFramesFieldName)}];
rows[rowCount] = { __depth: 1, __index: i };
rowCount++;
}
}
}
return rows;
`;
return new Function("frame", "nestedRowIndex", fnBody);
}
const RESERVED_ROW_KEYS = /* @__PURE__ */ new Set(["__depth", "__index", "__parentIndex"]);
function compileFrameToRecordsV2(frame, nestedFramesFieldName) {
const displayNames = frame.fields.map(getDisplayName);
const nestedName = (nestedFramesFieldName != null ? nestedFramesFieldName : "").length > 0 ? nestedFramesFieldName : void 0;
const nestedColIdx = nestedName ? displayNames.indexOf(nestedName) : -1;
return (frame2, nestedRowIndex) => {
var _a, _b, _c;
const values = frame2.fields.map((f) => f.values);
const frameLength = (_c = (_b = frame2.length) != null ? _b : (_a = values[0]) == null ? void 0 : _a.length) != null ? _c : 0;
const proto = {
__depth: -1,
__index: -1,
__parentIndex: void 0
};
const descriptors = {};
for (let j = 0; j < displayNames.length; j++) {
const name = displayNames[j];
if (j === nestedColIdx || RESERVED_ROW_KEYS.has(name)) {
continue;
}
const col = values[j];
descriptors[name] = {
enumerable: true,
get() {
return col[this.__index];
}
};
}
Object.defineProperties(proto, descriptors);
const hasParent = nestedRowIndex != null;
const nestedValues = nestedColIdx === -1 ? void 0 : values[nestedColIdx];
const createRow = (index, depth) => {
const row = Object.create(proto);
row.__depth = depth;
row.__index = index;
if (hasParent) {
row.__parentIndex = nestedRowIndex;
}
return row;
};
if (nestedValues === void 0) {
const result = Array(frameLength);
for (let i = 0; i < frameLength; i++) {
result[i] = createRow(i, 0);
}
return result;
}
const rows = [];
for (let i = 0; i < frameLength; i++) {
rows.push(createRow(i, 0));
if (nestedValues[i]) {
rows.push({ __depth: 1, __index: i });
}
}
return rows;
};
}
const compare = new Intl.Collator("en", { sensitivity: "base", numeric: true }).compare;
const strCompare = (a, b) => compare(String(a != null ? a : ""), String(b != null ? b : ""));
const numCompare = (a, b) => {
if (a === b) {
return 0;
}
if (a == null) {
return -1;
}
if (b == null) {
return 1;
}
return Number(a) - Number(b);
};
const frameCompare = (a, b) => {
var _a, _b;
return ((_a = a == null ? void 0 : a.value) != null ? _a : 0) - ((_b = b == null ? void 0 : b.value) != null ? _b : 0);
};
function getComparator(sortColumnType) {
switch (sortColumnType) {
// Handle sorting for frame type fields (sparklines)
case FieldType.frame:
return frameCompare;
case FieldType.time:
case FieldType.number:
case FieldType.boolean:
return numCompare;
case FieldType.string:
case FieldType.enum:
default:
return strCompare;
}
}
const TABLE_CELL_GAUGE_DISPLAY_MODES_TO_DISPLAY_MODES = {
[TableCellDisplayMode.BasicGauge]: BarGaugeDisplayMode.Basic,
[TableCellDisplayMode.GradientGauge]: BarGaugeDisplayMode.Gradient,
[TableCellDisplayMode.LcdGauge]: BarGaugeDisplayMode.Lcd
};
const TABLE_CELL_COLOR_BACKGROUND_DISPLAY_MODES_TO_DISPLAY_MODES = {
[TableCellDisplayMode.ColorBackground]: TableCellBackgroundDisplayMode.Gradient,
[TableCellDisplayMode.ColorBackgroundSolid]: TableCellBackgroundDisplayMode.Basic
};
function migrateTableDisplayModeToCellOptions(displayMode) {
switch (displayMode) {
// In the case of the gauge we move to a different option
case TableCellDisplayMode.BasicGauge:
case TableCellDisplayMode.GradientGauge:
case TableCellDisplayMode.LcdGauge:
return {
type: TableCellDisplayMode.Gauge,
mode: TABLE_CELL_GAUGE_DISPLAY_MODES_TO_DISPLAY_MODES[displayMode]
};
// Also true in the case of the color background
case TableCellDisplayMode.ColorBackground:
case TableCellDisplayMode.ColorBackgroundSolid:
return {
type: TableCellDisplayMode.ColorBackground,
mode: TABLE_CELL_COLOR_BACKGROUND_DISPLAY_MODES_TO_DISPLAY_MODES[displayMode]
};
// catching a nonsense case: `displayMode`: 'custom' should pre-date the CustomCell.
// if it doesn't, we need to just nope out and return an auto cell.
case TableCellDisplayMode.Custom:
return {
type: TableCellDisplayMode.Auto
};
default:
return {
type: displayMode
};
}
}
function rowKeyGetter(row) {
return row.__index + "_" + row.__depth;
}
const getIsNestedTable = (fields) => fields.some(({ type }) => type === FieldType.nestedFrames);
const calculateFooterHeight = (fields) => {
var _a, _b, _c, _d;
let maxReducerCount = 0;
for (const field of fields) {
maxReducerCount = Math.max(maxReducerCount, (_d = (_c = (_b = (_a = field.config.custom) == null ? void 0 : _a.footer) == null ? void 0 : _b.reducers) == null ? void 0 : _c.length) != null ? _d : 0);
}
return maxReducerCount > 0 ? maxReducerCount * TABLE.LINE_HEIGHT + TABLE.CELL_PADDING * 2 : 0;
};
const getDisplayName = (field) => {
var _a, _b;
return (_b = (_a = field.state) == null ? void 0 : _a.displayName) != null ? _b : field.name;
};
const predicateByName = (name) => (f) => f.name === name || getDisplayName(f) === name;
function getVisibleFields(fields) {
return fields.filter((field) => {
var _a, _b;
return field.type !== FieldType.nestedFrames && ((_b = (_a = field.config.custom) == null ? void 0 : _a.hideFrom) == null ? void 0 : _b.viz) !== true;
});
}
function getColumnTypes(fields) {
return fields.reduce((acc, field) => {
var _a, _b, _c;
switch (field.type) {
case FieldType.nestedFrames:
return { ...acc, ...getColumnTypes((_c = (_b = (_a = field.values[0]) == null ? void 0 : _a[0]) == null ? void 0 : _b.fields) != null ? _c : []) };
default:
return { ...acc, [getDisplayName(field)]: field.type };
}
}, {});
}
function computeColWidths(fields, availWidth) {
let autoCount = 0;
let definedWidth = 0;
return fields.map((field) => {
var _a, _b;
const width = (_b = (_a = field.config.custom) == null ? void 0 : _a.width) != null ? _b : 0;
if (width === 0) {
autoCount++;
} else {
definedWidth += width;
}
return width;
}).map(
(width, i) => {
var _a, _b;
return width || Math.max((_b = (_a = fields[i].config.custom) == null ? void 0 : _a.minWidth) != null ? _b : COLUMN.DEFAULT_WIDTH, (availWidth - definedWidth) / autoCount);
}
);
}
function buildNestedColumnWidthsMap(fields, widths) {
return new Map(
fields.map((field, idx) => [getDisplayName(field), { type: "resized", width: widths[idx] }])
);
}
function getApplyToRowBgFn(fields, getCellColorInlineStyles) {
for (const field of fields) {
const cellOptions = getCellOptions(field);
const fieldDisplay = field.display;
if (fieldDisplay !== void 0 && cellOptions.type === TableCellDisplayMode.ColorBackground && cellOptions.applyToRow === true) {
return (rowIndex) => getCellColorInlineStyles(cellOptions, fieldDisplay(field.values[rowIndex]), true);
}
}
}
function canFieldBeColorized(cellType, applyToRowBgFn) {
return cellType === TableCellDisplayMode.ColorBackground || cellType === TableCellDisplayMode.ColorText || Boolean(applyToRowBgFn);
}
const displayJsonValue = (field, decimals) => {
const origDisplay = field.display;
return (value) => {
const displayValue = origDisplay(value, decimals);
let jsonText;
if (!Array.isArray(value) && !isPlainObject(value)) {
const formattedValue = formattedValueToString(displayValue);
try {
const parsed = JSON.parse(formattedValue);
jsonText = JSON.stringify(parsed, null, " ");
} catch (e) {
jsonText = formattedValue;
}
} else {
jsonText = JSON.stringify(value, null, " ");
}
return { ...displayValue, text: jsonText };
};
};
function prepareSparklineValue(value, field) {
if (Array.isArray(value)) {
return {
y: {
name: `${field.name}-sparkline`,
type: FieldType.number,
values: value,
config: {}
}
};
}
if (isDataFrame(value)) {
const timeField = value.fields.find((x) => x.type === FieldType.time);
const numberField = value.fields.find((x) => x.type === FieldType.number);
if (timeField && numberField) {
return { x: timeField, y: numberField };
}
}
return;
}
function isPlainObject(value) {
return typeof value === "object" && value != null && !Array.isArray(value);
}
function buildInspectValue(value, field, formatGeometry) {
const cellOptions = getCellOptions(field);
let inspectValue;
let mode = TableCellInspectorMode.text;
if (field.type === FieldType.geo && isGeometry(value)) {
inspectValue = formatGeometry ? formatGeometry(value) : JSON.stringify(value, null, " ");
mode = TableCellInspectorMode.code;
} else if (cellOptions.type === TableCellDisplayMode.Sparkline || getAutoRendererDisplayMode(field) === TableCellDisplayMode.Sparkline) {
const fieldSparkline = prepareSparklineValue(value, field);
inspectValue = "[";
if (fieldSparkline != null) {
const buildValString = fieldSparkline.x != null ? (idx) => {
var _a, _b;
return `[${(_a = fieldSparkline.x.values[idx]) != null ? _a : "null"}, ${(_b = fieldSparkline.y.values[idx]) != null ? _b : "null"}]`;
} : (idx) => {
var _a;
return `${(_a = fieldSparkline.y.values[idx]) != null ? _a : "null"}`;
};
for (let i = 0; i < fieldSparkline.y.values.length; i++) {
inspectValue += `
${buildValString(i)}${i === fieldSparkline.y.values.length - 1 ? "\n" : ","}`;
}
}
inspectValue += "]";
mode = TableCellInspectorMode.code;
} else if (cellOptions.type === TableCellDisplayMode.JSONView || Array.isArray(value) || isPlainObject(value)) {
let toStringify = value;
if (typeof value === "string") {
try {
toStringify = JSON.parse(value);
} catch (e) {
}
}
inspectValue = JSON.stringify(toStringify, null, " ");
mode = TableCellInspectorMode.code;
} else {
inspectValue = String(value != null ? value : "");
}
return [inspectValue, mode];
}
function getSummaryCellTextAlign(textAlign, cellType) {
if (cellType === TableCellDisplayMode.Gauge) {
return {
left: "right",
right: "left",
center: "center"
}[textAlign];
}
return textAlign;
}
let warnedAboutStyleJsonSet = /* @__PURE__ */ new Set();
function parseStyleJson(rawValue) {
if (typeof rawValue === "string") {
try {
const parsedJsonValue = JSON.parse(rawValue);
if (parsedJsonValue != null && typeof parsedJsonValue === "object" && !Array.isArray(parsedJsonValue)) {
return parsedJsonValue;
}
} catch (e) {
if (!warnedAboutStyleJsonSet.has(rawValue)) {
console.error(`encountered invalid cell style JSON: ${rawValue}`, e);
warnedAboutStyleJsonSet.add(rawValue);
}
}
}
}
const IS_SAFARI_26 = (() => {
if (navigator == null) {
return false;
}
const userAgent = navigator.userAgent;
const safariVersionMatch = userAgent.match(/Version\/(\d+)\.(\d+)/);
if (!safariVersionMatch) {
return false;
}
const majorVersion = +safariVersionMatch[1];
const minorVersion = +safariVersionMatch[2];
return majorVersion === 26 && minorVersion <= 1;
})();
const getStableRowKey = (rowIndex, frame) => {
var _a, _b;
const key = (_b = (_a = frame == null ? void 0 : frame.meta) == null ? void 0 : _a.custom) == null ? void 0 : _b.stableRowKey;
return key != null ? String(key) : String(rowIndex);
};
export { IS_SAFARI_26, SINGLE_LINE_ESTIMATE_THRESHOLD, applyFilter, applySort, buildCellHeightMeasurers, buildHeaderHeightMeasurers, buildInspectValue, buildNestedColumnWidthsMap, calculateFooterHeight, canFieldBeColorized, compileFrameToRecordsV1, compileFrameToRecordsV2, computeColWidths, createTypographyContext, displayJsonValue, extractPixelValue, getAlignment, getAlignmentFactor, getApplyToRowBgFn, getCellColorInlineStylesFactory, getCellLinks, getCellOptions, getColumnTypes, getComparator, getDataLinksHeightMeasurer, getDefaultRowHeight, getDisplayName, getIsNestedTable, getJustifyContent, getPillCellHeightMeasurer, getRowHeight, getStableRowKey, getSummaryCellTextAlign, getTextHeightEstimator, getTextHeightMeasurerFromUwrapCount, getVisibleFields, isCellInspectEnabled, migrateTableDisplayModeToCellOptions, parseStyleJson, predicateByName, prepareSparklineValue, rowKeyGetter, shouldTextOverflow, shouldTextWrap };
//# sourceMappingURL=utils.mjs.map