@grafana/ui
Version:
Grafana Components Library
166 lines (163 loc) • 6.35 kB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import { useState, useCallback } from 'react';
import { FIELD_NAME_FACET_KEY } from '@grafana/data';
import { Trans } from '@grafana/i18n';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { Checkbox } from '../Forms/Checkbox.mjs';
import { Icon } from '../Icon/Icon.mjs';
"use strict";
function FacetedLabelsFilter({ labels, selected, onChange, dimmed }) {
const styles = useStyles2(getStyles);
const [expandedKeys, setExpandedKeys] = useState({});
const labelKeys = Object.keys(labels);
const toggleExpanded = useCallback((key) => {
setExpandedKeys((prev) => ({ ...prev, [key]: !prev[key] }));
}, []);
const toggleValue = useCallback(
(key, value) => {
var _a;
const current = (_a = selected[key]) != null ? _a : [];
const next = current.includes(value) ? current.filter((v) => v !== value) : [...current, value];
onChange({ ...selected, [key]: next });
},
[selected, onChange]
);
const toggleAllForKey = useCallback(
(key) => {
var _a;
const values = labels[key];
if (!values) {
return;
}
const current = (_a = selected[key]) != null ? _a : [];
const allSelected = current.length === values.length;
onChange({ ...selected, [key]: allSelected ? [] : [...values] });
},
[labels, selected, onChange]
);
const seriesValues = labels[FIELD_NAME_FACET_KEY];
const realLabelKeys = labelKeys.filter((key) => key !== FIELD_NAME_FACET_KEY);
if (!seriesValues && realLabelKeys.length === 0) {
return null;
}
const renderCheckboxList = (key, values, className) => {
var _a;
const selectedValues = (_a = selected[key]) != null ? _a : [];
return /* @__PURE__ */ jsxs("div", { className, children: [
values.map((value) => /* @__PURE__ */ jsx(
Checkbox,
{
label: value,
value: selectedValues.includes(value),
onChange: () => toggleValue(key, value),
className: styles.checkbox
},
value
)),
/* @__PURE__ */ jsx("button", { type: "button", className: styles.toggleAll, onClick: () => toggleAllForKey(key), children: selectedValues.length === values.length ? /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.viz-legend.faceted-deselect-all", children: "Deselect all" }) : /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.viz-legend.faceted-select-all", children: "Select all" }) })
] });
};
return /* @__PURE__ */ jsxs("div", { className: cx(styles.container, dimmed && styles.dimmed), "data-testid": "faceted-labels-filter", children: [
seriesValues && /* @__PURE__ */ jsxs("div", { className: styles.section, children: [
/* @__PURE__ */ jsx("span", { className: styles.sectionLabel, children: /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.viz-legend.faceted-by-name", children: "By name" }) }),
renderCheckboxList(FIELD_NAME_FACET_KEY, seriesValues, styles.checkboxList)
] }),
realLabelKeys.length > 0 && /* @__PURE__ */ jsxs("div", { className: styles.section, children: [
/* @__PURE__ */ jsx("span", { className: styles.sectionLabel, children: /* @__PURE__ */ jsx(Trans, { i18nKey: "grafana-ui.viz-legend.faceted-by-labels", children: "By labels" }) }),
realLabelKeys.map((key) => {
var _a, _b;
const selectedValues = (_a = selected[key]) != null ? _a : [];
const isExpanded = (_b = expandedKeys[key]) != null ? _b : false;
return /* @__PURE__ */ jsxs("div", { className: styles.labelGroup, children: [
/* @__PURE__ */ jsxs("button", { type: "button", className: styles.labelKey, onClick: () => toggleExpanded(key), children: [
/* @__PURE__ */ jsx(Icon, { name: isExpanded ? "angle-down" : "angle-right", size: "sm" }),
/* @__PURE__ */ jsx("span", { className: styles.keyName, children: key }),
selectedValues.length > 0 && /* @__PURE__ */ jsx("span", { className: styles.count, children: selectedValues.length })
] }),
isExpanded && renderCheckboxList(key, labels[key], styles.checkboxListIndented)
] }, key);
})
] })
] });
}
FacetedLabelsFilter.displayName = "FacetedLabelsFilter";
const getStyles = (theme) => ({
container: css({
display: "flex",
flexDirection: "column",
alignItems: "stretch",
minWidth: "150px",
padding: theme.spacing(1.5, 1, 1, 1),
gap: theme.spacing(1)
}),
dimmed: css({
opacity: 0.5
}),
section: css({
display: "flex",
flexDirection: "column"
}),
sectionLabel: css({
fontSize: theme.typography.bodySmall.fontSize,
fontWeight: theme.typography.fontWeightMedium,
color: theme.colors.text.secondary,
marginBottom: theme.spacing(0.25)
}),
toggleAll: css({
all: "unset",
cursor: "pointer",
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.link,
marginTop: theme.spacing(0.25),
"&:hover": {
textDecoration: "underline"
}
}),
labelGroup: css({
display: "flex",
flexDirection: "column"
}),
labelKey: css({
all: "unset",
display: "flex",
alignItems: "center",
gap: theme.spacing(0.5),
cursor: "pointer",
padding: theme.spacing(0.25, 0),
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.text.primary,
"&:hover": {
color: theme.colors.text.maxContrast
}
}),
keyName: css({
fontWeight: theme.typography.fontWeightMedium,
fontFamily: theme.typography.fontFamilyMonospace
}),
count: css({
fontSize: theme.typography.bodySmall.fontSize,
color: theme.colors.primary.text,
fontWeight: theme.typography.fontWeightMedium
}),
checkboxList: css({
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: theme.spacing(0.25),
padding: theme.spacing(0, 0, 0.5, 0.5)
}),
checkboxListIndented: css({
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: theme.spacing(0.25),
padding: theme.spacing(0, 0, 0.5, 2.5)
}),
checkbox: css({
fontSize: theme.typography.bodySmall.fontSize,
fontFamily: theme.typography.fontFamilyMonospace
})
});
export { FacetedLabelsFilter };
//# sourceMappingURL=FacetedLabelsFilter.mjs.map