@grafana/ui
Version:
Grafana Components Library
132 lines (129 loc) • 5.12 kB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
import { css, cx } from '@emotion/css';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { useOverlay } from '@react-aria/overlays';
import { forwardRef, Children, useState, useRef, createRef, useLayoutEffect } from 'react';
import { t } from '@grafana/i18n';
import { useTheme2 } from '../../themes/ThemeContext.mjs';
import { getPortalContainer } from '../Portal/Portal.mjs';
import { ToolbarButton } from './ToolbarButton.mjs';
"use strict";
const ToolbarButtonRow = forwardRef(
({ alignment = "left", className, children, ...rest }, ref) => {
const childrenWithoutNull = Children.toArray(children).filter((child) => child != null);
const [childVisibility, setChildVisibility] = useState(Array(childrenWithoutNull.length).fill(false));
const containerRef = useRef(null);
const [showOverflowItems, setShowOverflowItems] = useState(false);
const overflowRef = useRef(null);
const overflowItemsRef = createRef();
const { overlayProps } = useOverlay(
{
onClose: () => setShowOverflowItems(false),
isDismissable: true,
isOpen: showOverflowItems,
shouldCloseOnInteractOutside: (element) => {
var _a;
const portalContainer = getPortalContainer();
return !((_a = overflowRef.current) == null ? void 0 : _a.contains(element)) && !portalContainer.contains(element);
}
},
overflowItemsRef
);
const { dialogProps } = useDialog({}, overflowItemsRef);
const theme = useTheme2();
const overflowButtonOrder = alignment === "left" ? childVisibility.indexOf(false) - 1 : childVisibility.length;
const styles = getStyles(theme, overflowButtonOrder, alignment);
useLayoutEffect(() => {
const intersectionObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.target instanceof HTMLElement && entry.target.parentNode) {
const index = Array.prototype.indexOf.call(entry.target.parentNode.children, entry.target);
setChildVisibility((prev) => {
const newVisibility = [...prev];
newVisibility[index] = entry.isIntersecting;
return newVisibility;
});
}
});
},
{
threshold: 1,
root: containerRef.current
}
);
if (containerRef.current) {
Array.from(containerRef.current.children).forEach((item) => {
if (item instanceof HTMLElement && item !== overflowRef.current) {
intersectionObserver.observe(item);
}
});
}
return () => intersectionObserver.disconnect();
}, [children]);
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: cx(styles.container, className), ...rest, children: [
childrenWithoutNull.map((child, index) => /* @__PURE__ */ jsx(
"div",
{
style: { order: index, visibility: childVisibility[index] ? "visible" : "hidden" },
className: styles.childWrapper,
children: child
},
index
)),
childVisibility.includes(false) && /* @__PURE__ */ jsxs("div", { ref: overflowRef, className: styles.overflowButton, children: [
/* @__PURE__ */ jsx(
ToolbarButton,
{
variant: showOverflowItems ? "active" : "default",
tooltip: t("grafana-ui.toolbar-button-row.show-more", "Show more items"),
onClick: () => setShowOverflowItems(!showOverflowItems),
icon: "ellipsis-v",
iconOnly: true,
narrow: true
}
),
showOverflowItems && /* @__PURE__ */ jsx(FocusScope, { contain: true, autoFocus: true, children: /* @__PURE__ */ jsx("div", { className: styles.overflowItems, ref: overflowItemsRef, ...overlayProps, ...dialogProps, children: childrenWithoutNull.map((child, index) => !childVisibility[index] && child) }) })
] })
] });
}
);
ToolbarButtonRow.displayName = "ToolbarButtonRow";
const getStyles = (theme, overflowButtonOrder, alignment) => ({
overflowButton: css({
order: overflowButtonOrder
}),
overflowItems: css({
alignItems: "center",
backgroundColor: theme.colors.background.primary,
borderRadius: theme.shape.radius.default,
boxShadow: theme.shadows.z2,
display: "flex",
flexWrap: "wrap",
gap: theme.spacing(1),
marginTop: theme.spacing(1),
maxWidth: "80vw",
padding: theme.spacing(0.5, 1),
position: "absolute",
right: 0,
top: "100%",
width: "max-content",
zIndex: theme.zIndex.dropdown
}),
container: css({
alignItems: "center",
display: "flex",
gap: theme.spacing(1),
justifyContent: alignment === "left" ? "flex-start" : "flex-end",
minWidth: 0,
position: "relative"
}),
childWrapper: css({
alignItems: "center",
display: "flex",
gap: theme.spacing(1)
})
});
export { ToolbarButtonRow };
//# sourceMappingURL=ToolbarButtonRow.mjs.map