UNPKG

@grafana/ui

Version:
888 lines (885 loc) • 31.8 kB
import { jsxs, Fragment, jsx } from 'react/jsx-runtime'; import 'react-data-grid/lib/styles.css'; import { css } from '@emotion/css'; import { useMemo, useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react'; import DataGrid, { Row } from 'react-data-grid'; import { useMeasure } from 'react-use'; import { ReducerID, fieldReducers, FieldType, getDefaultTimeRange, DataHoverEvent, DataHoverClearEvent, formattedValueToString } from '@grafana/data'; import { TableCellDisplayMode } from '@grafana/schema'; import { useTheme2, useStyles2 } from '../../../themes/ThemeContext.mjs'; import 'micro-memoize'; import '@emotion/react'; import 'tinycolor2'; import '../../../utils/skeleton.mjs'; import { Trans, t } from '../../../utils/i18n.mjs'; import { ContextMenu } from '../../ContextMenu/ContextMenu.mjs'; import { MenuItem } from '../../Menu/MenuItem.mjs'; import { Pagination } from '../../Pagination/Pagination.mjs'; import '../../PanelChrome/LoadingIndicator.mjs'; import '@grafana/e2e-selectors'; import '../../../utils/dom.mjs'; import '../../../utils/colors.mjs'; import 'slate'; import 'lodash'; import '../../../utils/logger.mjs'; import '../../ElementSelectionContext/ElementSelectionContext.mjs'; import '../../Icon/Icon.mjs'; import '../../Text/Text.mjs'; import '../../Tooltip/Tooltip.mjs'; import '../../Dropdown/Dropdown.mjs'; import '../../ToolbarButton/ToolbarButton.mjs'; import '../../ToolbarButton/ToolbarButtonRow.mjs'; import '../../PanelChrome/TitleItem.mjs'; import { usePanelContext } from '../../PanelChrome/PanelContext.mjs'; import { TableCellInspector, TableCellInspectorMode } from '../TableCellInspector.mjs'; import { HeaderCell } from './Cells/HeaderCell.mjs'; import { RowExpander } from './Cells/RowExpander.mjs'; import { TableCellNG } from './Cells/TableCellNG.mjs'; import { TABLE, COLUMN } from './constants.mjs'; import { getIsNestedTable, getDefaultRowHeight, frameToRecords, getDisplayName, processNestedTableRows, getFooterItemNG, getCellHeightCalculator, getRowHeight, getTextAlign, getFooterStyles, shouldTextOverflow, handleSort, getComparator, getCellColors } from './utils.mjs'; function TableNG(props) { var _a, _b; const { cellHeight, enablePagination, enableVirtualization = true, fieldConfig, footerOptions, height, initialSortBy, noHeader, onCellFilterAdded, onColumnResize, onSortByChange, width, data, enableSharedCrosshair, showTypeIcons, replaceVariables } = props; const initialSortColumns = useMemo(() => { const initialSort = initialSortBy == null ? void 0 : initialSortBy.map(({ displayName, desc }) => { const matchingField = data.fields.find(({ state }) => (state == null ? void 0 : state.displayName) === displayName); const columnKey = (matchingField == null ? void 0 : matchingField.name) || displayName; return { columnKey, direction: desc ? "DESC" : "ASC" }; }); return initialSort != null ? initialSort : []; }, []); const [revId, setRevId] = useState(0); const [contextMenuProps, setContextMenuProps] = useState(null); const [isInspecting, setIsInspecting] = useState(false); const [isContextMenuOpen, setIsContextMenuOpen] = useState(false); const [filter, setFilter] = useState({}); const [page, setPage] = useState(0); const [, setResizeTrigger] = useState(0); const [, setReadyForRowHeightCalc] = useState(false); const [sortColumns, setSortColumns] = useState(initialSortColumns); const [expandedRows, setExpandedRows] = useState([]); const [isNestedTable, setIsNestedTable] = useState(false); const scrollPositionRef = useRef({ x: 0, y: 0 }); const [hasScroll, setHasScroll] = useState(false); const crossFilterOrder = useRef([]); const crossFilterRows = useRef({}); const headerCellRefs = useRef({}); const sortColumnsRef = useRef(initialSortColumns); const prevProps = useRef(props); const calcsRef = useRef([]); const [paginationWrapperRef, { height: paginationHeight }] = useMeasure(); const theme = useTheme2(); const panelContext = usePanelContext(); const isFooterVisible = Boolean((footerOptions == null ? void 0 : footerOptions.show) && ((_a = footerOptions.reducer) == null ? void 0 : _a.length)); const isCountRowsSet = Boolean( (footerOptions == null ? void 0 : footerOptions.countRows) && footerOptions.reducer && footerOptions.reducer.length && footerOptions.reducer[0] === ReducerID.count ); const tableRef = useRef(null); useEffect(() => { var _a2, _b2; if (prevProps.current.data.fields.length !== props.data.fields.length || ((_a2 = prevProps.current.fieldConfig) == null ? void 0 : _a2.overrides) !== (fieldConfig == null ? void 0 : fieldConfig.overrides) || ((_b2 = prevProps.current.fieldConfig) == null ? void 0 : _b2.defaults) !== (fieldConfig == null ? void 0 : fieldConfig.defaults)) { setRevId(revId + 1); } prevProps.current = props; }, [props, revId, fieldConfig == null ? void 0 : fieldConfig.overrides, fieldConfig == null ? void 0 : fieldConfig.defaults]); useLayoutEffect(() => { if (!isContextMenuOpen) { return; } function onClick(event) { setIsContextMenuOpen(false); } addEventListener("click", onClick); return () => { removeEventListener("click", onClick); }; }, [isContextMenuOpen]); useEffect(() => { const hasNestedFrames = getIsNestedTable(props.data); setIsNestedTable(hasNestedFrames); }, [props.data]); useEffect(() => { const el = tableRef.current; if (el) { const gridElement = el == null ? void 0 : el.element; if (gridElement) { setHasScroll( gridElement.scrollHeight > gridElement.clientHeight || gridElement.scrollWidth > gridElement.clientWidth ); } } }, []); const columnWidth = useMemo(() => { var _a2, _b2; setRevId(revId + 1); return ((_b2 = (_a2 = fieldConfig == null ? void 0 : fieldConfig.defaults) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.width) || "auto"; }, [fieldConfig]); const defaultRowHeight = getDefaultRowHeight(theme, cellHeight); const defaultLineHeight = theme.typography.body.lineHeight * theme.typography.fontSize; const panelPaddingHeight = theme.components.panel.padding * theme.spacing.gridSize * 2; const rows = useMemo(() => frameToRecords(props.data), [frameToRecords, props.data]); const columnTypes = useMemo( () => props.data.fields.reduce((acc, field) => ({ ...acc, [getDisplayName(field)]: field.type }), {}), [props.data.fields] ); const textWraps = useMemo( () => props.data.fields.reduce( (acc, field) => { var _a2, _b2, _c, _d; return { ...acc, [getDisplayName(field)]: (_d = (_c = (_b2 = (_a2 = field.config) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.cellOptions) == null ? void 0 : _c.wrapText) != null ? _d : false }; }, {} ), [props.data.fields] ); const textWrap = useMemo(() => Object.values(textWraps).some(Boolean), [textWraps]); const styles = useStyles2(getStyles); const getColumnWidths = useCallback(() => { const widths = {}; props.data.fields.forEach((field) => { var _a2, _b2; const displayName = getDisplayName(field); const configWidth = (_b2 = (_a2 = field.config) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.width; const totalWidth = typeof configWidth === "number" ? configWidth : COLUMN.DEFAULT_WIDTH; const contentWidth = totalWidth - 2 * TABLE.CELL_PADDING - 1; widths[displayName] = contentWidth; }); Object.keys(headerCellRefs.current).forEach((key) => { const headerCell = headerCellRefs.current[key]; if (headerCell.offsetWidth > 0) { widths[key] = headerCell.offsetWidth; } }); return widths; }, [props.data.fields]); const headersLength = useMemo(() => { return props.data.fields.length; }, [props.data.fields]); const fieldDisplayType = useMemo(() => { return props.data.fields.reduce((acc, field) => { var _a2, _b2, _c; if ((_c = (_b2 = (_a2 = field.config) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.cellOptions) == null ? void 0 : _c.type) { acc[getDisplayName(field)] = field.config.custom.cellOptions.type; } return acc; }, {}); }, [props.data.fields]); const fieldsData = useMemo( () => ({ headersLength, textWraps, columnTypes, fieldDisplayType, columnWidths: getColumnWidths() }), [textWraps, columnTypes, getColumnWidths, headersLength, fieldDisplayType] ); const filteredRows = useMemo(() => { const filterValues = Object.entries(filter); if (filterValues.length === 0) { crossFilterOrder.current = []; return rows; } const getDisplayedValue = (row, key) => { const field = props.data.fields.find((field2) => getDisplayName(field2) === key); if (!field || !field.display) { return ""; } const displayedValue = formattedValueToString(field.display(row[key])); return displayedValue; }; const filterKeys = new Set(filterValues.map(([key]) => key)); filterKeys.forEach((key) => { if (!crossFilterOrder.current.includes(key)) { crossFilterOrder.current.push(key); } }); crossFilterOrder.current = crossFilterOrder.current.filter((key) => filterKeys.has(key)); crossFilterRows.current = {}; if (isNestedTable) { return processNestedTableRows( rows, (parents) => parents.filter((row) => { for (const [key, value] of filterValues) { const displayedValue = getDisplayedValue(row, key); if (!value.filteredSet.has(displayedValue)) { return false; } if (!crossFilterRows.current[key]) { crossFilterRows.current[key] = [row]; } else { crossFilterRows.current[key].push(row); } } return true; }) ); } return rows.filter((row) => { for (const [key, value] of filterValues) { const displayedValue = getDisplayedValue(row, key); if (!value.filteredSet.has(displayedValue)) { return false; } if (!crossFilterRows.current[key]) { crossFilterRows.current[key] = [row]; } else { crossFilterRows.current[key].push(row); } } return true; }); }, [rows, filter, isNestedTable, props.data.fields]); const sortedRows = useMemo(() => { if (sortColumns.length === 0) { return filteredRows; } const compareRows = (a, b) => { let result = 0; for (let i = 0; i < sortColumns.length; i++) { const { columnKey, direction } = sortColumns[i]; const compare = getComparator(columnTypes[columnKey]); const sortDir = direction === "ASC" ? 1 : -1; result = sortDir * compare(a[columnKey], b[columnKey]); if (result !== 0) { break; } } return result; }; if (isNestedTable) { return processNestedTableRows(filteredRows, (parents) => [...parents].sort(compareRows)); } return filteredRows.slice().sort((a, b) => compareRows(a, b)); }, [filteredRows, sortColumns, columnTypes, isNestedTable]); const numRows = sortedRows.length; let headerCellHeight = TABLE.MAX_CELL_HEIGHT; if (noHeader) { headerCellHeight = 0; } else if (!noHeader && Object.keys(headerCellRefs.current).length > 0) { headerCellHeight = headerCellRefs.current[Object.keys(headerCellRefs.current)[0]].getBoundingClientRect().height; } let rowsPerPage = Math.floor( (height - headerCellHeight - TABLE.SCROLL_BAR_WIDTH - paginationHeight - panelPaddingHeight) / defaultRowHeight ); if (isFooterVisible) { rowsPerPage -= 1; } if (rowsPerPage < 1) { rowsPerPage = 1; } const numberOfPages = Math.ceil(numRows / rowsPerPage); if (page > numberOfPages) { setPage(numberOfPages - 1); } const itemsRangeStart = page * rowsPerPage + 1; let displayedEnd = itemsRangeStart + rowsPerPage - 1; if (displayedEnd > numRows) { displayedEnd = numRows; } const smallPagination = width < TABLE.PAGINATION_LIMIT; const paginatedRows = useMemo(() => { const pageOffset = page * rowsPerPage; return sortedRows.slice(pageOffset, pageOffset + rowsPerPage); }, [rows, sortedRows, page, rowsPerPage]); useMemo(() => { calcsRef.current = props.data.fields.map((field, index) => { var _a2, _b2, _c; if ((_a2 = field.state) == null ? void 0 : _a2.calcs) { (_b2 = field.state) == null ? true : delete _b2.calcs; } if (isCountRowsSet) { return index === 0 ? `${sortedRows.length}` : ""; } if (index === 0) { const footerCalcReducer = (_c = footerOptions == null ? void 0 : footerOptions.reducer) == null ? void 0 : _c[0]; return footerCalcReducer ? fieldReducers.get(footerCalcReducer).name : ""; } return getFooterItemNG(sortedRows, field, footerOptions); }); }, [sortedRows, props.data.fields, footerOptions, isCountRowsSet]); const onCellExpand = (rowIdx) => { if (!expandedRows.includes(rowIdx)) { setExpandedRows([...expandedRows, rowIdx]); } else { setExpandedRows(expandedRows.filter((id) => id !== rowIdx)); } setResizeTrigger((prev) => prev + 1); }; const { ctx, avgCharWidth } = useMemo(() => { const font = `${theme.typography.fontSize}px ${theme.typography.fontFamily}`; const canvas = document.createElement("canvas"); const ctx2 = canvas.getContext("2d"); const letterSpacing = 0.15; ctx2.letterSpacing = `${letterSpacing}px`; ctx2.font = font; let 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"; const txtWidth = ctx2.measureText(txt).width; const avgCharWidth2 = txtWidth / txt.length + letterSpacing; return { ctx: ctx2, font, avgCharWidth: avgCharWidth2 }; }, [theme.typography.fontSize, theme.typography.fontFamily]); const columns = useMemo( () => mapFrameToDataGrid({ frame: props.data, calcsRef, options: { columnTypes, textWraps, columnWidth, crossFilterOrder, crossFilterRows, defaultLineHeight, defaultRowHeight, expandedRows, filter, headerCellRefs, isCountRowsSet, onCellFilterAdded, ctx, onSortByChange, rows, setContextMenuProps, setFilter, setIsInspecting, setSortColumns, sortColumnsRef, styles, theme, showTypeIcons, replaceVariables, ...props }, handlers: { onCellExpand, onColumnResize }, // Adjust table width to account for the scroll bar width availableWidth: width - (hasScroll ? TABLE.SCROLL_BAR_WIDTH + TABLE.SCROLL_BAR_MARGIN : 0) }), [props.data, calcsRef, filter, expandedRows, expandedRows.length, footerOptions, width, hasScroll, sortedRows] // eslint-disable-line react-hooks/exhaustive-deps ); useLayoutEffect(() => { setReadyForRowHeightCalc(Object.keys(headerCellRefs.current).length > 0); }, [columns]); const renderMenuItems = () => { return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx( MenuItem, { label: t("grafana-ui.table.inspect-menu-label", "Inspect value"), onClick: () => { setIsInspecting(true); }, className: styles.menuItem } ) }); }; const cellHeightCalc = useMemo(() => { return getCellHeightCalculator(ctx, defaultLineHeight, defaultRowHeight, TABLE.CELL_PADDING); }, [ctx, defaultLineHeight, defaultRowHeight]); const calculateRowHeight = useCallback( (row) => { var _a2, _b2, _c, _d, _e; if (Number(row.__depth) === 1 && !expandedRows.includes(Number(row.__index))) { return 0; } else if (Number(row.__depth) === 1 && expandedRows.includes(Number(row.__index))) { const headerCount = ((_c = (_b2 = (_a2 = row == null ? void 0 : row.data) == null ? void 0 : _a2.meta) == null ? void 0 : _b2.custom) == null ? void 0 : _c.noHeader) ? 0 : 1; const rowCount = (_e = (_d = row.data) == null ? void 0 : _d.length) != null ? _e : 0; return Math.max(defaultRowHeight, defaultRowHeight * (rowCount + headerCount)); } return getRowHeight(row, cellHeightCalc, avgCharWidth, defaultRowHeight, fieldsData); }, [expandedRows, avgCharWidth, defaultRowHeight, fieldsData, cellHeightCalc] ); const handleScroll = (event) => { const target = event.currentTarget; scrollPositionRef.current = { x: target.scrollLeft, y: target.scrollTop }; }; useEffect(() => { if (initialSortColumns.length > 0) { setSortColumns(initialSortColumns); } }, [initialSortColumns]); useEffect(() => { var _a2; if ((_a2 = tableRef.current) == null ? void 0 : _a2.element) { tableRef.current.element.scrollLeft = scrollPositionRef.current.x; tableRef.current.element.scrollTop = scrollPositionRef.current.y; } }, [revId]); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( DataGrid, { ref: tableRef, className: styles.dataGrid, enableVirtualization, rows: enablePagination ? paginatedRows : sortedRows, columns, headerRowHeight: noHeader ? 0 : void 0, defaultColumnOptions: { sortable: true, resizable: true }, rowHeight: textWrap || isNestedTable ? calculateRowHeight : defaultRowHeight, style: { width, height: height - (enablePagination ? paginationHeight : 0) }, renderers: { renderRow: (key, props2) => myRowRenderer(key, props2, expandedRows, panelContext, data, enableSharedCrosshair != null ? enableSharedCrosshair : false) }, onScroll: handleScroll, onCellContextMenu: ({ row, column }, event) => { event.preventGridDefault(); event.preventDefault(); const cellValue = row[column.key]; setContextMenuProps({ // rowIdx: rows.indexOf(row), value: String(cellValue != null ? cellValue : ""), top: event.clientY, left: event.clientX }); setIsContextMenuOpen(true); }, sortColumns, bottomSummaryRows: isFooterVisible ? [{}] : void 0, onColumnResize: () => { if (textWrap) { setResizeTrigger((prev) => prev + 1); } } }, `DataGrid${revId}` ), enablePagination && /* @__PURE__ */ jsxs("div", { className: styles.paginationContainer, ref: paginationWrapperRef, children: [ /* @__PURE__ */ jsx( Pagination, { className: "table-ng-pagination", currentPage: page + 1, numberOfPages, showSmallVersion: smallPagination, onNavigate: (toPage) => { setPage(toPage - 1); } } ), !smallPagination && /* @__PURE__ */ jsx("div", { className: styles.paginationSummary, children: /* @__PURE__ */ jsxs(Trans, { i18nKey: "grafana-ui.table.pagination-summary", children: [ { itemsRangeStart }, " - ", { displayedEnd }, " of ", { numRows }, " rows" ] }) }) ] }), isContextMenuOpen && /* @__PURE__ */ jsx( ContextMenu, { x: (contextMenuProps == null ? void 0 : contextMenuProps.left) || 0, y: (contextMenuProps == null ? void 0 : contextMenuProps.top) || 0, renderMenuItems, focusOnOpen: false } ), isInspecting && /* @__PURE__ */ jsx( TableCellInspector, { mode: (_b = contextMenuProps == null ? void 0 : contextMenuProps.mode) != null ? _b : TableCellInspectorMode.text, value: contextMenuProps == null ? void 0 : contextMenuProps.value, onDismiss: () => { setIsInspecting(false); setContextMenuProps(null); } } ) ] }); } function mapFrameToDataGrid({ frame, calcsRef, options, handlers, availableWidth }) { const { columnTypes, textWraps, crossFilterOrder, crossFilterRows, defaultLineHeight, defaultRowHeight, expandedRows, filter, headerCellRefs, isCountRowsSet, onCellFilterAdded, ctx, onSortByChange, rows, setContextMenuProps, setFilter, setIsInspecting, setSortColumns, sortColumnsRef, styles, theme, timeRange, getActions, showTypeIcons, replaceVariables } = options; const { onCellExpand, onColumnResize } = handlers; const columns = []; const hasNestedFrames = getIsNestedTable(frame); if (hasNestedFrames) { const expanderField = { name: "", type: FieldType.other, config: {}, values: [] }; columns.push({ key: "expanded", name: "", field: expanderField, cellClass: styles.cell, colSpan(args) { return args.type === "ROW" && Number(args.row.__depth) === 1 ? frame.fields.length : 1; }, renderCell: ({ row }) => { var _a, _b, _c; if (Number(row.__depth) === 0) { const rowIdx = Number(row.__index); return /* @__PURE__ */ jsx( RowExpander, { height: defaultRowHeight, onCellExpand: () => onCellExpand(rowIdx), isExpanded: expandedRows.includes(rowIdx) } ); } let expandedColumns = []; let expandedRecords = []; if (row.data) { expandedColumns = mapFrameToDataGrid({ frame: row.data, calcsRef, options: { ...options }, handlers: { onCellExpand, onColumnResize }, availableWidth }); expandedRecords = frameToRecords(row.data); } return /* @__PURE__ */ jsx( DataGrid, { rows: expandedRecords, columns: expandedColumns, rowHeight: defaultRowHeight, className: styles.dataGrid, style: { height: "100%", overflow: "visible", marginLeft: COLUMN.EXPANDER_WIDTH - 1 }, headerRowHeight: ((_c = (_b = (_a = row.data) == null ? void 0 : _a.meta) == null ? void 0 : _b.custom) == null ? void 0 : _c.noHeader) ? 0 : void 0 } ); }, width: COLUMN.EXPANDER_WIDTH, minWidth: COLUMN.EXPANDER_WIDTH }); availableWidth -= COLUMN.EXPANDER_WIDTH; } let rowBg = void 0; for (const field of frame.fields) { const fieldOptions = field.config.custom; const cellOptionsExist = fieldOptions !== void 0 && fieldOptions.cellOptions !== void 0; if (cellOptionsExist && fieldOptions.cellOptions.type === TableCellDisplayMode.ColorBackground && fieldOptions.cellOptions.applyToRow) { rowBg = (rowIndex) => { const display = field.display(field.values[rowIndex]); const colors = getCellColors(theme, fieldOptions.cellOptions, display); return colors; }; } } let fieldCountWithoutWidth = 0; frame.fields.map((field, fieldIndex) => { var _a; if (field.type === FieldType.nestedFrames || ((_a = field.config.custom) == null ? void 0 : _a.hidden)) { return; } const fieldTableOptions = field.config.custom || {}; const key = getDisplayName(field); const justifyColumnContent = getTextAlign(field); const footerStyles = getFooterStyles(justifyColumnContent); if (fieldTableOptions.width) { availableWidth -= fieldTableOptions.width; } else { fieldCountWithoutWidth++; } columns.push({ key, name: field.name, field, cellClass: textWraps[getDisplayName(field)] ? styles.cellWrapped : styles.cell, renderCell: (props) => { var _a2, _b, _c, _d; const { row } = props; const cellType = (_d = (_c = (_b = (_a2 = field.config) == null ? void 0 : _a2.custom) == null ? void 0 : _b.cellOptions) == null ? void 0 : _c.type) != null ? _d : TableCellDisplayMode.Auto; const value = row[key]; return /* @__PURE__ */ jsx( TableCellNG, { frame, value, field, theme, timeRange: timeRange != null ? timeRange : getDefaultTimeRange(), height: defaultRowHeight, justifyContent: justifyColumnContent, rowIdx: row.__index, shouldTextOverflow: () => shouldTextOverflow( key, row, columnTypes, headerCellRefs, ctx, defaultLineHeight, defaultRowHeight, TABLE.CELL_PADDING, textWraps[getDisplayName(field)], field, cellType ), setIsInspecting, setContextMenuProps, getActions, rowBg, onCellFilterAdded, replaceVariables }, key ); }, renderSummaryCell: () => { if (isCountRowsSet && fieldIndex === 0) { return /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [ /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.table.count", children: "Count" }) }), /* @__PURE__ */ jsx("span", { children: calcsRef.current[fieldIndex] }) ] }); } return /* @__PURE__ */ jsx("div", { className: footerStyles.footerCell, children: calcsRef.current[fieldIndex] }); }, renderHeaderCell: ({ column, sortDirection }) => /* @__PURE__ */ jsx( HeaderCell, { column, rows, field, onSort: (columnKey, direction, isMultiSort) => { handleSort(columnKey, direction, isMultiSort, setSortColumns, sortColumnsRef); if (onSortByChange) { const sortByFields = sortColumnsRef.current.map(({ columnKey: columnKey2, direction: direction2 }) => ({ displayName: columnKey2, desc: direction2 === "DESC" })); onSortByChange(sortByFields); } }, direction: sortDirection, justifyContent: justifyColumnContent, filter, setFilter, onColumnResize, headerCellRefs, crossFilterOrder, crossFilterRows, showTypeIcons } ), width: fieldTableOptions.width, minWidth: fieldTableOptions.minWidth || COLUMN.DEFAULT_WIDTH }); }); let sharedWidth = availableWidth / fieldCountWithoutWidth; for (let i = fieldCountWithoutWidth; i > 0; i--) { for (const column of columns) { if (!column.width && column.minWidth > sharedWidth) { column.width = column.minWidth; availableWidth -= column.width; fieldCountWithoutWidth -= 1; sharedWidth = availableWidth / fieldCountWithoutWidth; } } } for (const column of columns) { if (!column.width) { column.width = sharedWidth; } column.minWidth = COLUMN.MIN_WIDTH; } return columns; } function myRowRenderer(key, props, expandedRows, panelContext, data, enableSharedCrosshair) { const { row } = props; const rowIdx = Number(row.__index); const isExpanded = expandedRows.includes(rowIdx); if (Number(row.__depth) === 1 && !isExpanded) { return null; } if (row.data) { return /* @__PURE__ */ jsx(Row, { ...props, "aria-expanded": isExpanded }, key); } return /* @__PURE__ */ jsx( Row, { ...props, onMouseEnter: () => onRowHover(rowIdx, panelContext, data, enableSharedCrosshair), onMouseLeave: () => onRowLeave(panelContext, enableSharedCrosshair) }, key ); } function onRowHover(idx, panelContext, frame, enableSharedCrosshair) { if (!enableSharedCrosshair) { return; } const timeField = frame.fields.find((f) => f.type === FieldType.time); if (!timeField) { return; } panelContext.eventBus.publish( new DataHoverEvent({ point: { time: timeField.values[idx] } }) ); } function onRowLeave(panelContext, enableSharedCrosshair) { if (!enableSharedCrosshair) { return; } panelContext.eventBus.publish(new DataHoverClearEvent()); } const getStyles = (theme) => ({ dataGrid: css({ "--rdg-background-color": theme.colors.background.primary, "--rdg-header-background-color": theme.colors.background.primary, "--rdg-border-color": "transparent", "--rdg-color": theme.colors.text.primary, "&:hover": { "--rdg-row-hover-background-color": theme.colors.emphasize(theme.colors.action.hover, 0.6) }, // If we rely solely on borderInlineEnd which is added from data grid, we // get a small gap where the gridCell borders meet the column header borders. // To avoid this, we can unset borderInlineEnd and set borderRight instead. ".rdg-cell": { borderInlineEnd: "unset", borderRight: `1px solid ${theme.colors.border.medium}`, "&:last-child": { borderRight: "none" } }, ".rdg-summary-row": { backgroundColor: theme.colors.background.primary, "--rdg-summary-border-color": theme.colors.border.medium, ".rdg-cell": { // Prevent collisions with custom cell components zIndex: 2, borderRight: "none" } }, // Due to stylistic choices, we do not want borders on the column headers // other than the bottom border. "div[role=columnheader]": { borderBottom: `1px solid ${theme.colors.border.medium}`, borderInlineEnd: "unset", ".r1y6ywlx7-0-0-beta-46": { "&:hover": { borderRight: `3px solid ${theme.colors.text.link}` } } }, "::-webkit-scrollbar": { width: TABLE.SCROLL_BAR_WIDTH, height: TABLE.SCROLL_BAR_WIDTH }, "::-webkit-scrollbar-thumb": { backgroundColor: "rgba(204, 204, 220, 0.16)", borderRadius: "4px" }, "::-webkit-scrollbar-track": { background: "transparent" }, "::-webkit-scrollbar-corner": { backgroundColor: "transparent" } }), menuItem: css({ maxWidth: "200px" }), cell: css({ "--rdg-border-color": theme.colors.border.medium, borderLeft: "none", whiteSpace: "nowrap", wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis", // Reset default cell styles for custom cell component styling paddingInline: "0" }), cellWrapped: css({ "--rdg-border-color": theme.colors.border.medium, borderLeft: "none", whiteSpace: "pre-line", wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis", // Reset default cell styles for custom cell component styling paddingInline: "0" }), paginationContainer: css({ alignItems: "center", display: "flex", justifyContent: "center", marginTop: "8px", width: "100%" }), paginationSummary: css({ color: theme.colors.text.secondary, fontSize: theme.typography.bodySmall.fontSize, display: "flex", justifyContent: "flex-end", padding: theme.spacing(0, 1, 0, 2) }) }); export { TableNG, mapFrameToDataGrid, myRowRenderer, onRowHover, onRowLeave }; //# sourceMappingURL=TableNG.mjs.map