UNPKG

@grafana/ui

Version:
742 lines (739 loc) • 28.3 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import 'react-data-grid/lib/styles.css'; import { clsx } from 'clsx'; import memoize from 'micro-memoize'; import { useMemo, useCallback, useState, useRef } from 'react'; import { DataGrid, Cell, Row } from 'react-data-grid'; import { FieldType, FALLBACK_COLOR, getDisplayProcessor, DataHoverEvent, DataHoverClearEvent } from '@grafana/data'; import { Trans } from '@grafana/i18n'; import { TableCellDisplayMode, FieldColorModeId, TableCellTooltipPlacement } from '@grafana/schema'; import { useTheme2, useStyles2 } from '../../../themes/ThemeContext.mjs'; import { getTextColorForBackground } from '../../../utils/colors.mjs'; import { Pagination } from '../../Pagination/Pagination.mjs'; import '../../PanelChrome/index.mjs'; import { DataLinksActionsTooltip } from '../DataLinksActionsTooltip.mjs'; import { TableCellInspector, TableCellInspectorMode } from '../TableCellInspector.mjs'; import '../types.mjs'; import { getCellRenderer, getCellSpecificStyles } from './Cells/renderers.mjs'; import { HeaderCell } from './components/HeaderCell.mjs'; import { RowExpander } from './components/RowExpander.mjs'; import { SummaryCell } from './components/SummaryCell.mjs'; import { TableCellActions } from './components/TableCellActions.mjs'; import { TableCellTooltip } from './components/TableCellTooltip.mjs'; import { COLUMN, TABLE } from './constants.mjs'; import { useColumnResize, useFilteredRows, useSortedRows, useScrollbarWidth, useColWidths, useHeaderHeight, useRowHeight, usePaginatedRows } from './hooks.mjs'; import { getGridStyles, getHeaderCellStyles, getCellActionStyles, getDefaultCellStyles, getLinkStyles, getMaxHeightCellStyles, getTooltipStyles } from './styles.mjs'; import { getVisibleFields, calculateFooterHeight, frameToRecords, getIsNestedTable, getDefaultRowHeight, getCellColorInlineStylesFactory, getApplyToRowBgFn, createTypographyContext, extractPixelValue, IS_SAFARI_26, applySort, getCellOptions, displayJsonValue, getAlignment, getJustifyContent, getDisplayName, isCellInspectEnabled, shouldTextOverflow, shouldTextWrap, canFieldBeColorized, predicateByName, parseStyleJson, getSummaryCellTextAlign, getCellLinks } from './utils.mjs'; import { usePanelContext } from '../../PanelChrome/PanelContext.mjs'; "use strict"; const EXPANDED_COLUMN_KEY = "expanded"; function TableNG(props) { var _a, _b, _c; const { cellHeight, data, disableSanitizeHtml, enablePagination = false, enableSharedCrosshair = false, enableVirtualization, frozenColumns = 0, getActions = () => [], height, initialSortBy, maxRowHeight: _maxRowHeight, noHeader, onCellFilterAdded, onColumnResize, onSortByChange, showTypeIcons, structureRev, timeRange, transparent, width } = props; const theme = useTheme2(); const styles = useStyles2(getGridStyles, enablePagination, transparent); const panelContext = usePanelContext(); const userCanExecuteActions = useMemo(() => { var _a2, _b2; return (_b2 = (_a2 = panelContext.canExecuteActions) == null ? void 0 : _a2.call(panelContext)) != null ? _b2 : false; }, [panelContext]); const getCellActions = useCallback( (field, rowIdx) => { if (!userCanExecuteActions) { return []; } return getActions(data, field, rowIdx); }, [getActions, data, userCanExecuteActions] ); const visibleFields = useMemo(() => getVisibleFields(data.fields), [data.fields]); const hasHeader = !noHeader; const hasFooter = useMemo( () => visibleFields.some((field) => { var _a2, _b2, _c2; return Boolean((_c2 = (_b2 = (_a2 = field.config.custom) == null ? void 0 : _a2.footer) == null ? void 0 : _b2.reducers) == null ? void 0 : _c2.length); }), [visibleFields] ); const footerHeight = useMemo( () => hasFooter ? calculateFooterHeight(visibleFields) : 0, [hasFooter, visibleFields] ); const resizeHandler = useColumnResize(onColumnResize); const rows = useMemo(() => frameToRecords(data), [data]); const hasNestedFrames = useMemo(() => getIsNestedTable(data.fields), [data]); const getTextColorForBackground$1 = useMemo(() => memoize(getTextColorForBackground, { maxSize: 1e3 }), []); const { rows: filteredRows, filter, setFilter, crossFilterOrder, crossFilterRows } = useFilteredRows(rows, data.fields, { hasNestedFrames }); const { rows: sortedRows, sortColumns, setSortColumns } = useSortedRows(filteredRows, data.fields, { hasNestedFrames, initialSortBy }); const [inspectCell, setInspectCell] = useState(null); const [tooltipState, setTooltipState] = useState(); const [expandedRows, setExpandedRows] = useState(() => /* @__PURE__ */ new Set()); const defaultRowHeight = useMemo( () => getDefaultRowHeight(theme, visibleFields, cellHeight), [theme, visibleFields, cellHeight] ); const gridRef = useRef(null); const scrollbarWidth = useScrollbarWidth(gridRef, height); const availableWidth = useMemo( () => (hasNestedFrames ? width - COLUMN.EXPANDER_WIDTH : width) - scrollbarWidth, [width, hasNestedFrames, scrollbarWidth] ); const getCellColorInlineStyles = useMemo(() => getCellColorInlineStylesFactory(theme), [theme]); const applyToRowBgFn = useMemo( () => { var _a2; return (_a2 = getApplyToRowBgFn(data.fields, getCellColorInlineStyles)) != null ? _a2 : void 0; }, [data.fields, getCellColorInlineStyles] ); const typographyCtx = useMemo( () => createTypographyContext( theme.typography.fontSize, theme.typography.fontFamily, extractPixelValue(theme.typography.body.letterSpacing) * theme.typography.fontSize ), [theme] ); const [widths, numFrozenColsFullyInView] = useColWidths(visibleFields, availableWidth, frozenColumns); const headerHeight = useHeaderHeight({ columnWidths: widths, fields: visibleFields, enabled: hasHeader, sortColumns, showTypeIcons: showTypeIcons != null ? showTypeIcons : false, typographyCtx }); const maxRowHeight = _maxRowHeight != null ? Math.max(TABLE.LINE_HEIGHT, _maxRowHeight) : void 0; const rowHeight = useRowHeight({ columnWidths: widths, fields: visibleFields, hasNestedFrames, defaultHeight: defaultRowHeight, expandedRows, typographyCtx, maxHeight: maxRowHeight }); const { rows: paginatedRows, page, setPage, numPages, pageRangeStart, pageRangeEnd, smallPagination } = usePaginatedRows(sortedRows, { enabled: enablePagination, width: availableWidth, height, footerHeight, headerHeight: hasHeader ? TABLE.HEADER_ROW_HEIGHT : 0, rowHeight }); const [footers, isUniformFooter] = useMemo(() => { var _a2, _b2, _c2, _d, _e; const footers2 = []; let isUniformFooter2 = true; let firstReducers; for (const field of visibleFields) { const footer = (_b2 = (_a2 = field.config) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.footer; footers2.push(footer); if (firstReducers === void 0 && ((_d = (_c2 = footer == null ? void 0 : footer.reducers) == null ? void 0 : _c2.length) != null ? _d : 0) > 0) { firstReducers = footer == null ? void 0 : footer.reducers; } else if (firstReducers !== void 0) { const reducers = footer == null ? void 0 : footer.reducers; if ((_e = reducers == null ? void 0 : reducers.length) != null ? _e : 0 > 0) { if (reducers.length !== firstReducers.length || reducers.some((r, idx) => (firstReducers == null ? void 0 : firstReducers[idx]) !== r)) { isUniformFooter2 = false; break; } } } } return [footers2, isUniformFooter2]; }, [visibleFields]); const rowHeightFn = useMemo(() => { if (typeof rowHeight === "function") { return rowHeight; } if (typeof rowHeight === "string") { return () => TABLE.MAX_CELL_HEIGHT; } return () => rowHeight; }, [rowHeight]); const renderRow = useMemo( () => renderRowFactory(data.fields, panelContext, expandedRows, enableSharedCrosshair), [data, enableSharedCrosshair, expandedRows, panelContext] ); const commonDataGridProps = useMemo( () => ({ enableVirtualization: !IS_SAFARI_26 && enableVirtualization !== false && rowHeight !== "auto", defaultColumnOptions: { minWidth: 50, resizable: true, sortable: true // draggable: true, }, onColumnResize: resizeHandler, onSortColumnsChange: (newSortColumns) => { setSortColumns(newSortColumns); onSortByChange == null ? void 0 : onSortByChange( newSortColumns.map(({ columnKey, direction }) => ({ displayName: columnKey, desc: direction === "DESC" })) ); }, sortColumns, rowHeight, bottomSummaryRows: hasFooter ? [{}] : void 0, summaryRowHeight: footerHeight, headerRowClass: styles.headerRow, headerRowHeight: noHeader ? 0 : TABLE.HEADER_ROW_HEIGHT }), [ enableVirtualization, hasFooter, resizeHandler, sortColumns, rowHeight, styles.headerRow, noHeader, setSortColumns, onSortByChange, footerHeight ] ); const buildNestedTableExpanderColumn = useCallback( (nestedColumns, hasNestedHeaders, renderers) => ({ key: EXPANDED_COLUMN_KEY, name: "", field: { name: "", type: FieldType.other, config: {}, values: [] }, cellClass(row) { if (row.__depth !== 0) { return styles.cellNested; } return; }, colSpan(args) { return args.type === "ROW" && args.row.__depth === 1 ? data.fields.length : 1; }, renderCell: ({ row }) => { if (row.__depth === 0) { const rowIdx = row.__index; return /* @__PURE__ */ jsx( RowExpander, { isExpanded: expandedRows.has(rowIdx), onCellExpand: () => { if (expandedRows.has(rowIdx)) { expandedRows.delete(rowIdx); } else { expandedRows.add(rowIdx); } setExpandedRows(new Set(expandedRows)); } } ); } const nestedData = row.data; if (!nestedData) { return null; } const expandedRecords = applySort(frameToRecords(nestedData), nestedData.fields, sortColumns); if (!expandedRecords.length) { return /* @__PURE__ */ jsx("div", { className: styles.noDataNested, children: /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.table.nested-table.no-data", children: "No data" }) }); } return /* @__PURE__ */ jsx( DataGrid, { ...commonDataGridProps, className: clsx(styles.grid, styles.gridNested), headerRowClass: clsx(styles.headerRow, { [styles.displayNone]: !hasNestedHeaders }), headerRowHeight: hasNestedHeaders ? TABLE.HEADER_HEIGHT : 0, columns: nestedColumns, rows: expandedRecords, renderers } ); }, width: COLUMN.EXPANDER_WIDTH, minWidth: COLUMN.EXPANDER_WIDTH }), [commonDataGridProps, data.fields.length, expandedRows, sortColumns, styles] ); const fromFields = useCallback( (f, widths2) => { const result = { columns: [], cellRootRenderers: {} }; let lastRowIdx = -1; let rowCellStyle = { color: void 0, background: void 0 }; f.forEach((field, i) => { var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k; const cellOptions = getCellOptions(field); const cellType = cellOptions.type; if (cellType === TableCellDisplayMode.Pill && ((_b2 = (_a2 = field.config.mappings) == null ? void 0 : _a2.length) != null ? _b2 : 0 > 0)) { field = { ...field, config: { ...field.config, color: { ...field.config.color, mode: FieldColorModeId.Fixed, fixedColor: (_d = (_c2 = field.config.color) == null ? void 0 : _c2.fixedColor) != null ? _d : FALLBACK_COLOR } } }; field.display = getDisplayProcessor({ field, theme }); } if (cellType === TableCellDisplayMode.JSONView || field.type === FieldType.other) { field.display = displayJsonValue(field); } const textAlign = getAlignment(field); const justifyContent = getJustifyContent(textAlign); const displayName = getDisplayName(field); const headerCellClass = getHeaderCellStyles(theme, justifyContent); const CellType = getCellRenderer(field, cellOptions); const cellInspect = isCellInspectEnabled(field); const showFilters = Boolean(field.config.filterable && onCellFilterAdded != null); const showActions = cellInspect || showFilters; const width2 = widths2[i]; const cellActionClassName = showActions ? clsx("table-cell-actions", getCellActionStyles(theme, textAlign)) : void 0; const shouldOverflow = !IS_SAFARI_26 && rowHeight !== "auto" && (shouldTextOverflow(field) || Boolean(maxRowHeight)); const textWrap = rowHeight === "auto" || shouldTextWrap(field); const canBeColorized = canFieldBeColorized(cellType, applyToRowBgFn); const cellStyleOptions = { textAlign, textWrap, shouldOverflow, maxHeight: maxRowHeight }; const defaultCellStyles = getDefaultCellStyles(theme, cellStyleOptions); const cellSpecificStyles = getCellSpecificStyles(cellType, field, theme, cellStyleOptions); const linkStyles = getLinkStyles(theme, canBeColorized); const cellParentStyles = clsx(defaultCellStyles, linkStyles); const maxHeightClassName = maxRowHeight ? getMaxHeightCellStyles(theme, cellStyleOptions) : void 0; const styleFieldValue = (_e = field.config.custom) == null ? void 0 : _e.styleField; const styleField = styleFieldValue ? data.fields.find(predicateByName(styleFieldValue)) : void 0; const styleFieldName = styleField ? getDisplayName(styleField) : void 0; const hasValidStyleField = Boolean(styleFieldName); const renderCellRoot2 = (key, props2) => { const rowIdx = props2.row.__index; if (rowIdx !== lastRowIdx) { lastRowIdx = rowIdx; rowCellStyle.color = void 0; rowCellStyle.background = void 0; if (applyToRowBgFn != null) { rowCellStyle = { ...rowCellStyle, ...applyToRowBgFn(rowIdx) }; } } let style = { ...rowCellStyle }; if (canBeColorized) { const value = props2.row[props2.column.key]; const displayValue = field.display(value); const cellColorStyles = getCellColorInlineStyles(cellOptions, displayValue, applyToRowBgFn != null); Object.assign(style, cellColorStyles); } if (hasValidStyleField) { style = { ...style, ...parseStyleJson(props2.row[styleFieldName]) }; } return /* @__PURE__ */ jsx( Cell, { ...props2, className: clsx( props2.className, cellParentStyles, cellSpecificStyles != null && { [cellSpecificStyles]: maxRowHeight == null } ), style }, key ); }; result.cellRootRenderers[displayName] = renderCellRoot2; const renderBasicCellContent = (props2) => { const rowIdx = props2.row.__index; const value = props2.row[props2.column.key]; const height2 = rowHeightFn(props2.row); const frame = data; let result2 = /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( CellType, { cellOptions, frame, field, height: height2, rowIdx, theme, value, width: width2, timeRange, cellInspect, showFilters, getActions: getCellActions, disableSanitizeHtml, getTextColorForBackground: getTextColorForBackground$1 } ), showActions && /* @__PURE__ */ jsx( TableCellActions, { field, value, displayName, cellInspect, showFilters, className: cellActionClassName, setInspectCell, onCellFilterAdded } ) ] }); if (maxRowHeight != null) { result2 = /* @__PURE__ */ jsx("div", { className: clsx(maxHeightClassName, cellSpecificStyles), children: result2 }); } return result2; }; let renderCellContent = renderBasicCellContent; const tooltipFieldName = (_g = (_f = field.config.custom) == null ? void 0 : _f.tooltip) == null ? void 0 : _g.field; if (tooltipFieldName) { const tooltipField = data.fields.find(predicateByName(tooltipFieldName)); if (tooltipField) { const tooltipDisplayName = getDisplayName(tooltipField); const tooltipCellOptions = getCellOptions(tooltipField); const tooltipFieldRenderer = getCellRenderer(tooltipField, tooltipCellOptions); const tooltipCellStyleOptions = { textAlign: getAlignment(tooltipField), textWrap: shouldTextWrap(tooltipField), shouldOverflow: false, maxHeight: maxRowHeight }; const tooltipCanBeColorized = canFieldBeColorized(tooltipCellOptions.type, applyToRowBgFn); const tooltipDefaultStyles = getDefaultCellStyles(theme, tooltipCellStyleOptions); const tooltipSpecificStyles = getCellSpecificStyles( tooltipCellOptions.type, tooltipField, theme, tooltipCellStyleOptions ); const tooltipLinkStyles = getLinkStyles(theme, tooltipCanBeColorized); const tooltipClasses = getTooltipStyles(theme, textAlign); const placement = (_j = (_i = (_h = field.config.custom) == null ? void 0 : _h.tooltip) == null ? void 0 : _i.placement) != null ? _j : TableCellTooltipPlacement.Auto; const tooltipWidth = placement === TableCellTooltipPlacement.Left || placement === TableCellTooltipPlacement.Right ? (_k = tooltipField.config.custom) == null ? void 0 : _k.width : width2; const tooltipProps = { cellOptions: tooltipCellOptions, classes: tooltipClasses, className: clsx( tooltipClasses.tooltipContent, tooltipDefaultStyles, tooltipSpecificStyles, tooltipLinkStyles ), data, disableSanitizeHtml, field: tooltipField, getActions: getCellActions, getTextColorForBackground: getTextColorForBackground$1, gridRef, placement, renderer: tooltipFieldRenderer, tooltipField, theme, width: tooltipWidth }; renderCellContent = (props2) => { const tooltipHeight = rowHeightFn(props2.row); let tooltipStyle = { ...rowCellStyle }; if (tooltipCanBeColorized) { const tooltipDisplayValue = tooltipField.display(props2.row[tooltipDisplayName]); const tooltipCellColorStyles = getCellColorInlineStyles( tooltipCellOptions, tooltipDisplayValue, applyToRowBgFn != null ); Object.assign(tooltipStyle, tooltipCellColorStyles); } return /* @__PURE__ */ jsx( TableCellTooltip, { ...tooltipProps, height: tooltipHeight, rowIdx: props2.row.__index, style: tooltipStyle, children: renderBasicCellContent(props2) } ); }; } } result.columns.push({ field, key: displayName, name: displayName, width: width2, headerCellClass, frozen: Math.min(frozenColumns, numFrozenColsFullyInView) > i, renderCell: renderCellContent, renderHeaderCell: ({ column, sortDirection }) => /* @__PURE__ */ jsx( HeaderCell, { column, rows, field, filter, setFilter, crossFilterOrder, crossFilterRows, direction: sortDirection, showTypeIcons } ), renderSummaryCell: () => /* @__PURE__ */ jsx( SummaryCell, { rows: sortedRows, footers, field, colIdx: i, textAlign: getSummaryCellTextAlign(textAlign, cellType), rowLabel: isUniformFooter && i === 0, hideLabel: isUniformFooter && i !== 0 } ) }); }); return result; }, [ applyToRowBgFn, crossFilterOrder, crossFilterRows, data, disableSanitizeHtml, filter, footers, frozenColumns, getCellActions, getCellColorInlineStyles, getTextColorForBackground$1, isUniformFooter, maxRowHeight, numFrozenColsFullyInView, onCellFilterAdded, rows, rowHeight, rowHeightFn, setFilter, sortedRows, showTypeIcons, theme, timeRange ] ); const firstRowNestedData = useMemo( () => { var _a2; return hasNestedFrames ? (_a2 = rows.find((r) => r.data)) == null ? void 0 : _a2.data : void 0; }, [hasNestedFrames, rows] ); const [nestedFieldWidths] = useColWidths((_a = firstRowNestedData == null ? void 0 : firstRowNestedData.fields) != null ? _a : [], availableWidth); const { columns, cellRootRenderers } = useMemo(() => { var _a2, _b2; const result = fromFields(visibleFields, widths); if (!firstRowNestedData) { return result; } const hasNestedHeaders = ((_b2 = (_a2 = firstRowNestedData.meta) == null ? void 0 : _a2.custom) == null ? void 0 : _b2.noHeader) !== true; const renderRow2 = renderRowFactory(firstRowNestedData.fields, panelContext, expandedRows, enableSharedCrosshair); const { columns: nestedColumns, cellRootRenderers: nestedCellRootRenderers } = fromFields( firstRowNestedData.fields, nestedFieldWidths ); const expanderCellRenderer = (key, props2) => /* @__PURE__ */ jsx(Cell, { ...props2 }, key); result.cellRootRenderers[EXPANDED_COLUMN_KEY] = expanderCellRenderer; result.columns.unshift( buildNestedTableExpanderColumn(nestedColumns, hasNestedHeaders, { renderRow: renderRow2, renderCell: (key, props2) => nestedCellRootRenderers[props2.column.key](key, props2) }) ); return result; }, [ buildNestedTableExpanderColumn, enableSharedCrosshair, expandedRows, firstRowNestedData, fromFields, nestedFieldWidths, panelContext, visibleFields, widths ]); const structureRevColumns = useMemo(() => columns, [columns, structureRev]); const renderCellRoot = useCallback( (key, props2) => cellRootRenderers[props2.column.key](key, props2), [cellRootRenderers] ); const itemsRangeStart = pageRangeStart; const displayedEnd = pageRangeEnd; const numRows = sortedRows.length; let rendered = /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( DataGrid, { ...commonDataGridProps, ref: gridRef, className: styles.grid, columns: structureRevColumns, rows: paginatedRows, headerRowClass: clsx(styles.headerRow, { [styles.displayNone]: noHeader }), headerRowHeight: headerHeight, onCellClick: ({ column, row }, { clientX, clientY, preventGridDefault, target }) => { var _a2; const field = columns[column.idx].field; if (target instanceof HTMLElement && // this walks up the tree to find either a faux link wrapper or the cell root // it then only proceeds if we matched the faux link wrapper ((_a2 = target.closest("a[aria-haspopup], .rdg-cell")) == null ? void 0 : _a2.matches("a"))) { const rowIdx = row.__index; setTooltipState({ coords: { clientX, clientY }, links: getCellLinks(field, rowIdx), actions: getCellActions(field, rowIdx) }); preventGridDefault(); } }, onCellKeyDown: hasNestedFrames ? (_, event) => { if (event.isDefaultPrevented()) { event.preventGridDefault(); } } : null, renderers: { renderRow, renderCell: renderCellRoot } } ), enablePagination && /* @__PURE__ */ jsxs("div", { className: styles.paginationContainer, children: [ /* @__PURE__ */ jsx( Pagination, { className: "table-ng-pagination", currentPage: page + 1, numberOfPages: numPages, 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" ] }) }) ] }), tooltipState && /* @__PURE__ */ jsx( DataLinksActionsTooltip, { links: (_b = tooltipState.links) != null ? _b : [], actions: tooltipState.actions, coords: tooltipState.coords, onTooltipClose: () => setTooltipState(void 0) } ), inspectCell && /* @__PURE__ */ jsx( TableCellInspector, { mode: (_c = inspectCell.mode) != null ? _c : TableCellInspectorMode.text, value: inspectCell.value, onDismiss: () => setInspectCell(null) } ) ] }); if (IS_SAFARI_26) { rendered = /* @__PURE__ */ jsx("div", { className: styles.safariWrapper, children: rendered }); } return rendered; } const renderRowFactory = (fields, panelContext, expandedRows, enableSharedCrosshair) => ( // eslint-disable-next-line react/display-name (key, props) => { const { row } = props; const rowIdx = row.__index; const isExpanded = expandedRows.has(rowIdx); if (row.__depth === 1 && !isExpanded) { return null; } if (row.data) { return /* @__PURE__ */ jsx(Row, { ...props, "aria-expanded": isExpanded }, key); } const handlers = {}; if (enableSharedCrosshair) { const timeField = fields.find((f) => f.type === FieldType.time); if (timeField) { handlers.onMouseEnter = () => { panelContext.eventBus.publish( new DataHoverEvent({ point: { time: timeField == null ? void 0 : timeField.values[rowIdx] } }) ); }; handlers.onMouseLeave = () => { panelContext.eventBus.publish(new DataHoverClearEvent()); }; } } return /* @__PURE__ */ jsx(Row, { ...props, ...handlers }, key); } ); export { TableNG }; //# sourceMappingURL=TableNG.mjs.map