@grafana/ui
Version:
Grafana Components Library
199 lines (196 loc) • 6.65 kB
JavaScript
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { useMemo, createElement } from 'react';
import { cx, css } from '@emotion/css';
import { Trans } from '@grafana/i18n';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { Button } from '../Button/Button.mjs';
import { Icon } from '../Icon/Icon.mjs';
import { useLimit } from '../List/hooks.mjs';
import { LegendTableItem } from './VizLegendTableItem.mjs';
"use strict";
const nameSortKey = "Name";
const naturalCompare = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" }).compare;
const VizLegendTable = ({
items,
sortBy: sortKey,
sortDesc,
itemRenderer,
className,
onToggleSort,
onLabelClick,
onLabelMouseOver,
onLabelMouseOut,
readonly,
isSortable,
limit = 0,
filterAction,
placement,
overflow
}) => {
var _a, _b;
const styles = useStyles2(getStyles, placement);
const header = {
[nameSortKey]: ""
};
for (const item of items) {
if (item.getDisplayValues) {
for (const displayValue of item.getDisplayValues()) {
header[(_a = displayValue.title) != null ? _a : "?"] = (_b = displayValue.description) != null ? _b : "";
}
}
}
if (sortKey != null) {
let itemVals = /* @__PURE__ */ new Map();
items.forEach((item) => {
if (sortKey !== nameSortKey && item.getDisplayValues) {
const stat = item.getDisplayValues().find((stat2) => stat2.title === sortKey);
const val = stat == null || Number.isNaN(stat.numeric) ? -Infinity : stat.numeric;
itemVals.set(item, val);
}
});
let sortMult = sortDesc ? -1 : 1;
if (sortKey === nameSortKey) {
items.sort((a, b) => {
return sortMult * naturalCompare(a.label, b.label);
});
} else {
items.sort((a, b) => {
var _a2, _b2;
const aVal = (_a2 = itemVals.get(a)) != null ? _a2 : 0;
const bVal = (_b2 = itemVals.get(b)) != null ? _b2 : 0;
return sortMult * (aVal - bVal);
});
}
}
const [curLimit, setLimit] = useLimit(limit);
const limitedItems = useMemo(() => curLimit > 0 ? items.slice(0, curLimit) : items, [items, curLimit]);
const hasMixedAxes = useMemo(() => {
var _a2, _b2;
const firstYAxis = (_b2 = (_a2 = items[0]) == null ? void 0 : _a2.yAxis) != null ? _b2 : 1;
return items.some((item) => item.yAxis !== firstYAxis);
}, [items]);
if (!itemRenderer) {
itemRenderer = (item, index) => /* @__PURE__ */ jsx(
LegendTableItem,
{
item,
onLabelClick,
onLabelMouseOver,
onLabelMouseOut,
readonly,
hasMixedAxes,
overflow
},
`${item.label}-${index}`
);
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(
"table",
{
className: cx(styles.grid, className),
style: {
gridTemplateColumns: `min-content minmax(55px, auto) ${"min-content ".repeat(Object.keys(header).length - 1)}`
},
children: [
/* @__PURE__ */ jsx("thead", { className: styles.header, children: /* @__PURE__ */ jsxs("tr", { children: [
/* @__PURE__ */ jsx("th", { children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: /* @__PURE__ */ jsx(Trans, { i18nKey: "legend.container.series-color-and-icon", children: "Series color" }) }) }),
Object.keys(header).map((columnTitle, i) => /* @__PURE__ */ createElement(
"th",
{
...sortKey === columnTitle ? { "aria-sort": sortDesc ? "descending" : "ascending" } : null,
title: header[columnTitle],
key: columnTitle,
className: cx({
[styles.headerSortable]: Boolean(onToggleSort),
[styles.nameHeader]: isSortable,
[styles.calcHeader]: i > 0,
[styles.withIcon]: sortKey === columnTitle,
"sr-only": !isSortable
}),
onClick: () => {
if (onToggleSort && isSortable) {
onToggleSort(columnTitle);
}
}
},
columnTitle === nameSortKey && filterAction && // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
/* @__PURE__ */ jsx("span", { className: styles.filterAction, onClick: (e) => e.stopPropagation(), children: filterAction }),
columnTitle,
sortKey === columnTitle && /* @__PURE__ */ jsx(Icon, { size: "xs", name: sortDesc ? "angle-down" : "angle-up" })
))
] }) }),
/* @__PURE__ */ jsx("tbody", { children: limitedItems.map(itemRenderer) })
]
}
),
curLimit > 0 && items.length > curLimit && /* @__PURE__ */ jsx(Button, { fill: "text", variant: "primary", size: "sm", onClick: () => setLimit(0), className: styles.showAll, children: /* @__PURE__ */ jsxs(Trans, { i18nKey: "legend.container.show-all-series", className: styles.showAll, children: [
"...show all ",
{ total: items.length },
" items"
] }) })
] });
};
const getStyles = (theme, placement = "bottom") => ({
header: css({
position: "sticky",
top: 0,
backgroundColor: theme.colors.background.primary,
color: theme.colors.primary.text
}),
nameHeader: css({
textAlign: "left"
}),
calcHeader: css({
textAlign: "right"
}),
withIcon: css({
paddingRight: "4px"
}),
headerSortable: css({
cursor: "pointer"
}),
filterAction: css({
marginLeft: theme.spacing(0.5),
display: "inline-flex",
verticalAlign: "middle"
}),
showAll: css({
justifyContent: "right"
}),
grid: css({
display: "grid",
width: "100%",
// non-layout
fontSize: theme.typography.bodySmall.fontSize,
textAlign: "right",
whiteSpace: "nowrap",
"tbody,thead,tfoot,tr": {
display: "grid",
gridColumn: "1 / -1",
gridTemplateColumns: "subgrid"
},
tr: {
borderBottom: `1px solid ${theme.colors.border.weak}`
},
"th,td": {
display: "block",
alignContent: "center",
whiteSpace: "nowrap",
// non-layout
padding: theme.spacing(0.25, 1),
// series color/icon column
"&:nth-child(1)": {
paddingLeft: theme.spacing(1)
},
// series name column
"&:nth-child(2)": {
overflow: "hidden",
textOverflow: "ellipsis",
maxWidth: placement === "right" ? 600 : void 0
}
}
})
});
export { VizLegendTable };
//# sourceMappingURL=VizLegendTable.mjs.map