@grafana/ui
Version:
Grafana Components Library
142 lines (139 loc) • 4.58 kB
JavaScript
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import { offset, flip, shift, arrow, useFloating, autoUpdate, useClick, useDismiss, useInteractions, FloatingFocusManager, FloatingArrow } from '@floating-ui/react';
import { memo, useRef, useState, cloneElement, isValidElement } from 'react';
import { t } from '@grafana/i18n';
import { useTheme2, useStyles2 } from '../../themes/ThemeContext.mjs';
import { getPlacement, buildTooltipTheme } from '../../utils/tooltipUtils.mjs';
import { IconButton } from '../IconButton/IconButton.mjs';
const Toggletip = memo(
({
children,
theme = "info",
placement = "auto",
content,
title,
closeButton = true,
onClose,
footer,
fitContent = false,
onOpen,
show
}) => {
const arrowRef = useRef(null);
const grafanaTheme = useTheme2();
const styles = useStyles2(getStyles);
const style = styles[theme];
const [controlledVisible, setControlledVisible] = useState(show);
const isOpen = show != null ? show : controlledVisible;
const middleware = [
offset(8),
flip({
fallbackAxisSideDirection: "end",
// see https://floating-ui.com/docs/flip#combining-with-shift
crossAxis: false,
boundary: document.body
}),
shift(),
arrow({
element: arrowRef
})
];
const { context, refs, floatingStyles } = useFloating({
open: isOpen,
placement: getPlacement(placement),
onOpenChange: (open) => {
if (show === void 0) {
setControlledVisible(open);
}
if (!open) {
onClose == null ? void 0 : onClose();
} else {
onOpen == null ? void 0 : onOpen();
}
},
middleware,
whileElementsMounted: autoUpdate,
strategy: "fixed"
});
const click = useClick(context);
const dismiss = useDismiss(context);
const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, click]);
return /* @__PURE__ */ jsxs(Fragment, { children: [
cloneElement(children, {
ref: refs.setReference,
tabIndex: 0,
"aria-expanded": isOpen,
...getReferenceProps()
}),
isOpen && /* @__PURE__ */ jsx(FloatingFocusManager, { context, modal: false, closeOnFocusOut: false, children: /* @__PURE__ */ jsxs(
"div",
{
"data-testid": "toggletip-content",
className: cx(style.container, {
[styles.fitContent]: fitContent
}),
ref: refs.setFloating,
style: floatingStyles,
...getFloatingProps(),
children: [
/* @__PURE__ */ jsx(
FloatingArrow,
{
strokeWidth: 0.3,
stroke: grafanaTheme.colors.border.weak,
className: style.arrow,
ref: arrowRef,
context
}
),
Boolean(title) && /* @__PURE__ */ jsx("div", { className: style.header, children: title }),
closeButton && /* @__PURE__ */ jsx("div", { className: style.headerClose, children: /* @__PURE__ */ jsx(
IconButton,
{
"aria-label": t("grafana-ui.toggletip.close", "Close"),
name: "times",
"data-testid": "toggletip-header-close",
onClick: () => {
setControlledVisible(false);
onClose == null ? void 0 : onClose();
}
}
) }),
/* @__PURE__ */ jsxs("div", { className: style.body, children: [
(typeof content === "string" || isValidElement(content)) && content,
typeof content === "function" && content({})
] }),
Boolean(footer) && /* @__PURE__ */ jsx("div", { className: style.footer, children: footer })
]
}
) })
] });
}
);
Toggletip.displayName = "Toggletip";
const getStyles = (theme) => {
const info = buildTooltipTheme(
theme,
theme.colors.background.primary,
theme.colors.border.weak,
theme.components.tooltip.text,
{ topBottom: 2, rightLeft: 2 }
);
const error = buildTooltipTheme(
theme,
theme.colors.error.main,
theme.colors.error.main,
theme.colors.error.contrastText,
{ topBottom: 2, rightLeft: 2 }
);
return {
info,
error,
fitContent: css({
maxWidth: "fit-content"
})
};
};
export { Toggletip, getStyles };
//# sourceMappingURL=Toggletip.mjs.map