import memoize from 'micro-memoize';
import WKT from 'ol/format/WKT';
import Geometry from 'ol/geom/Geometry';
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 { inferPills } from './Cells/PillCell.mjs';
import { getCellRenderer, AutoCellRenderer, getAutoRendererDisplayMode } from './Cells/renderers.mjs';
import { TABLE, COLUMN } from './constants.mjs';

"use strict";
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 "auto";
  }
  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 (field.type === FieldType.string && 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, rowIdx, 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 cellValueRaw = rowIdx === -1 ? getDisplayName(field) : field.values[rowIdx];
      if (cellValueRaw != null) {
        const colWidth = columnWidths[fieldIdx];
        const estimatedHeight = measurer(cellValueRaw, colWidth, field, rowIdx, lineHeight);
        if (estimatedHeight > maxHeight) {
          maxHeight = estimatedHeight;
          maxValue = cellValueRaw;
          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, rowIdx, 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);
};
function applySort(rows, fields, sortColumns, columnTypes = getColumnTypes(fields), hasNestedFrames = getIsNestedTable(fields)) {
  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;
  };
  if (hasNestedFrames) {
    return processNestedTableRows(rows, (parents) => [...parents].sort(compareRows));
  }
  return [...rows].sort(compareRows);
}
const frameToRecords = (frame) => {
  const fnBody = `
    const rows = Array(frame.length);
    const values = frame.fields.map(f => f.values);
    let rowCount = 0;
    for (let i = 0; i < frame.length; i++) {
      rows[rowCount] = {
        __depth: 0,
        __index: i,
        ${frame.fields.map((field, fieldIdx) => `${JSON.stringify(getDisplayName(field))}: values[${fieldIdx}][i]`).join(",")}
      };
      rowCount += 1;
      if (rows[rowCount-1]['__nestedFrames']){
        const childFrame = rows[rowCount-1]['__nestedFrames'];
        rows[rowCount] = {__depth: 1, __index: i, data: childFrame[0]}
        rowCount += 1;
      }
    }
    return rows;
  `;
  const convert = new Function("frame", fnBody);
  return convert(frame);
};
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
      };
  }
}
const getIsNestedTable = (fields) => fields.some(({ type }) => type === FieldType.nestedFrames);
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 = [];
  processedParents.forEach((row) => {
    result.push(row);
    const childRow = childRows.get(row.__index);
    if (childRow) {
      result.push(childRow);
    }
  });
  return result;
};
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 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) {
  const cellOptions = getCellOptions(field);
  let inspectValue;
  let mode = TableCellInspectorMode.text;
  if (field.type === FieldType.geo && value instanceof Geometry) {
    inspectValue = new WKT().writeGeometry(value, {
      featureProjection: "EPSG:3857",
      dataProjection: "EPSG:4326"
    });
    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)) {
    inspectValue = JSON.stringify(value, 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+)\./);
  return safariVersionMatch && parseInt(safariVersionMatch[1], 10) === 26;
})();

export { IS_SAFARI_26, SINGLE_LINE_ESTIMATE_THRESHOLD, applySort, buildCellHeightMeasurers, buildHeaderHeightMeasurers, buildInspectValue, calculateFooterHeight, canFieldBeColorized, computeColWidths, createTypographyContext, displayJsonValue, extractPixelValue, frameToRecords, getAlignment, getAlignmentFactor, getApplyToRowBgFn, getCellColorInlineStylesFactory, getCellLinks, getCellOptions, getColumnTypes, getComparator, getDataLinksHeightMeasurer, getDefaultRowHeight, getDisplayName, getIsNestedTable, getJustifyContent, getPillCellHeightMeasurer, getRowHeight, getSummaryCellTextAlign, getTextHeightEstimator, getTextHeightMeasurerFromUwrapCount, getVisibleFields, isCellInspectEnabled, migrateTableDisplayModeToCellOptions, parseStyleJson, predicateByName, prepareSparklineValue, processNestedTableRows, shouldTextOverflow, shouldTextWrap };
//# sourceMappingURL=utils.mjs.map
