UNPKG

@grafana/ui

Version:
142 lines (139 loc) 4.58 kB
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