@grafana/ui
Version:
Grafana Components Library
256 lines (251 loc) • 9.14 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var jsxRuntime = require('react/jsx-runtime');
var css = require('@emotion/css');
var React = require('react');
var reactTable = require('react-table');
var data = require('@grafana/data');
var i18n = require('@grafana/i18n');
var ThemeContext = require('../../themes/ThemeContext.cjs');
var Icon = require('../Icon/Icon.cjs');
var Pagination = require('../Pagination/Pagination.cjs');
var Tooltip = require('../Tooltip/Tooltip.cjs');
var utils = require('./utils.cjs');
"use strict";
const getStyles = (theme) => {
const rowHoverBg = theme.colors.emphasize(theme.colors.background.primary, 0.03);
return {
container: css.css({
display: "flex",
gap: theme.spacing(2),
flexDirection: "column",
width: "100%",
overflowX: "auto"
}),
cell: css.css({
padding: theme.spacing(1),
minWidth: theme.spacing(3)
}),
table: css.css({
borderRadius: theme.shape.radius.default,
width: "100%"
}),
disableGrow: css.css({
width: 0
}),
header: css.css({
borderBottom: `1px solid ${theme.colors.border.weak}`,
minWidth: theme.spacing(3),
"&, & > button": {
position: "relative",
whiteSpace: "nowrap",
padding: theme.spacing(1)
},
"& > button": {
"&:after": {
content: '"\\00a0"'
},
width: "100%",
height: "100%",
background: "none",
border: "none",
paddingRight: theme.spacing(2.5),
textAlign: "left",
fontWeight: theme.typography.fontWeightMedium
}
}),
row: css.css({
label: "row",
borderBottom: `1px solid ${theme.colors.border.weak}`,
"&:hover": {
backgroundColor: rowHoverBg
},
"&:last-child": {
borderBottom: 0
}
}),
expandedRow: css.css({
label: "expanded-row-content",
borderBottom: "none"
}),
expandedContentCell: css.css({
borderBottom: `1px solid ${theme.colors.border.weak}`,
position: "relative",
padding: theme.spacing(2, 2, 2, 5),
"&:before": {
content: '""',
position: "absolute",
width: "1px",
top: 0,
left: "16px",
bottom: theme.spacing(2),
background: theme.colors.border.medium
}
}),
expandedContentRow: css.css({
label: "expanded-row-content"
}),
sortableHeader: css.css({
/* increases selector's specificity so that it always takes precedence over default styles */
"&&": {
padding: 0
}
})
};
};
function InteractiveTable({
autoResetPage,
className,
columns,
data: data$1,
getRowId,
headerTooltips,
pageSize = 0,
renderExpandedRow,
showExpandAll = false,
fetchData,
initialSortBy = [],
disableSortRemove
}) {
const styles = ThemeContext.useStyles2(getStyles);
const tableColumns = React.useMemo(() => {
return utils.getColumns(columns, showExpandAll);
}, [columns, showExpandAll]);
const id = React.useId();
const getRowHTMLID = React.useCallback(
(row) => {
return `${id}-${row.id}`.replace(/\s/g, "");
},
[id]
);
const tableHooks = [reactTable.useSortBy, reactTable.useExpanded];
const multiplePages = data$1.length > pageSize;
const paginationEnabled = pageSize > 0;
if (paginationEnabled) {
tableHooks.push(reactTable.usePagination);
}
const tableInstance = reactTable.useTable(
{
columns: tableColumns,
data: data$1,
autoResetExpanded: false,
autoResetPage: !!autoResetPage,
// If undefined, we want to treat this as false to prevent page reset by default
autoResetSortBy: false,
disableMultiSort: true,
// If fetchData is provided, we disable client-side sorting
manualSortBy: Boolean(fetchData),
disableSortRemove,
getRowId,
initialState: {
hiddenColumns: [
!renderExpandedRow && utils.EXPANDER_CELL_ID,
...tableColumns.filter((col) => !(col.visible ? col.visible(data$1) : true)).map((c) => c.id).filter(data.isTruthy)
].filter(data.isTruthy),
sortBy: initialSortBy
}
},
...tableHooks
);
const { getTableProps, getTableBodyProps, headerGroups, prepareRow } = tableInstance;
const { sortBy } = tableInstance.state;
React.useEffect(() => {
if (fetchData) {
fetchData({ sortBy });
}
}, [sortBy, fetchData]);
React.useEffect(() => {
if (paginationEnabled) {
tableInstance.setPageSize(pageSize);
}
}, [paginationEnabled, pageSize, tableInstance.setPageSize, tableInstance]);
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.container, children: [
/* @__PURE__ */ jsxRuntime.jsxs("table", { ...getTableProps(), className: css.cx(styles.table, className), children: [
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: headerGroups.map((headerGroup) => {
const { key, ...headerRowProps } = headerGroup.getHeaderGroupProps();
return /* @__PURE__ */ jsxRuntime.jsx("tr", { ...headerRowProps, children: headerGroup.headers.map((column) => {
const { key: key2, ...headerCellProps } = column.getHeaderProps();
const headerTooltip = headerTooltips == null ? void 0 : headerTooltips[column.id];
return /* @__PURE__ */ jsxRuntime.jsx(
"th",
{
...headerCellProps,
className: css.cx(styles.header, column.widthClass, {
[styles.disableGrow]: column.width === 0,
[styles.sortableHeader]: column.canSort
}),
...column.isSorted && { "aria-sort": column.isSortedDesc ? "descending" : "ascending" },
children: /* @__PURE__ */ jsxRuntime.jsx(ColumnHeader, { column, headerTooltip })
},
key2
);
}) }, key);
}) }),
/* @__PURE__ */ jsxRuntime.jsx("tbody", { ...getTableBodyProps(), children: (paginationEnabled ? tableInstance.page : tableInstance.rows).map((row) => {
prepareRow(row);
const { key, ...otherRowProps } = row.getRowProps();
const rowId = getRowHTMLID(row);
const isExpanded = row.isExpanded;
return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
/* @__PURE__ */ jsxRuntime.jsx("tr", { ...otherRowProps, className: css.cx(styles.row, isExpanded && styles.expandedRow), children: row.cells.map((cell) => {
const { key: key2, ...otherCellProps } = cell.getCellProps();
return /* @__PURE__ */ jsxRuntime.jsx("td", { ...otherCellProps, className: css.cx(styles.cell, cell.column.widthClass), children: cell.render("Cell", { __rowID: rowId }) }, key2);
}) }),
isExpanded && renderExpandedRow && /* @__PURE__ */ jsxRuntime.jsx("tr", { ...otherRowProps, id: rowId, className: styles.expandedContentRow, children: /* @__PURE__ */ jsxRuntime.jsx("td", { className: styles.expandedContentCell, colSpan: row.cells.length, children: renderExpandedRow(row.original) }) })
] }, key);
}) })
] }),
paginationEnabled && multiplePages && /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx(
Pagination.Pagination,
{
currentPage: tableInstance.state.pageIndex + 1,
numberOfPages: tableInstance.pageOptions.length,
onNavigate: (toPage) => tableInstance.gotoPage(toPage - 1)
}
) })
] });
}
const getColumnHeaderStyles = (theme) => ({
sortIcon: css.css({
position: "absolute",
top: theme.spacing(1)
}),
headerTooltipIcon: css.css({
marginLeft: theme.spacing(0.5)
})
});
function ColumnHeader({
column: { canSort, render, isSorted, isSortedDesc, getSortByToggleProps, Header, id },
headerTooltip
}) {
const styles = ThemeContext.useStyles2(getColumnHeaderStyles);
const { onClick } = getSortByToggleProps();
const children = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
render("Header"),
headerTooltip && /* @__PURE__ */ jsxRuntime.jsx(Tooltip.Tooltip, { theme: "info-alt", content: headerTooltip.content, placement: "top-end", children: /* @__PURE__ */ jsxRuntime.jsx(
Icon.Icon,
{
className: styles.headerTooltipIcon,
name: headerTooltip.iconName || "info-circle",
"data-testid": "header-tooltip-icon"
}
) }),
isSorted && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: styles.sortIcon, children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { name: isSortedDesc ? "angle-down" : "angle-up" }) })
] });
if (canSort) {
return /* @__PURE__ */ jsxRuntime.jsx(
"button",
{
"aria-label": i18n.t("grafana-ui.interactive-table.aria-label-sort-column", "Sort column {{columnName}}", {
columnName: typeof Header === "string" ? Header : id
}),
type: "button",
onClick,
children
}
);
}
return children;
}
exports.InteractiveTable = InteractiveTable;
//# sourceMappingURL=InteractiveTable.cjs.map