UNPKG

@grafana/ui

Version:
256 lines (251 loc) • 9.14 kB
'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