UNPKG

@grafana/ui

Version:
204 lines (201 loc) • 6.97 kB
import { jsxs, jsx, Fragment } from 'react/jsx-runtime'; import { css } from '@emotion/css'; import clsx from 'clsx'; import { useState, useRef, useEffect } from 'react'; import { useStyles2 } from '../../themes/ThemeContext.mjs'; import { InlineToast } from '../InlineToast/InlineToast.mjs'; import { Tooltip } from '../Tooltip/Tooltip.mjs'; import { VizTooltipColorIndicator, ColorIndicatorPosition } from './VizTooltipColorIndicator.mjs'; import { VizTooltipColorPlacement } from './types.mjs'; "use strict"; var LabelValueTypes = /* @__PURE__ */ ((LabelValueTypes2) => { LabelValueTypes2["label"] = "label"; LabelValueTypes2["value"] = "value"; return LabelValueTypes2; })(LabelValueTypes || {}); const SUCCESSFULLY_COPIED_TEXT = "Copied to clipboard"; const SHOW_SUCCESS_DURATION = 2 * 1e3; const HORIZONTAL_PX_PER_CHAR = 7; const CAN_COPY = Boolean(navigator.clipboard && window.isSecureContext); const VizTooltipRow = ({ label, value, color, colorIndicator, colorPlacement = VizTooltipColorPlacement.first, justify, isActive = false, marginRight, isPinned = false, lineStyle, showValueScroll, isHiddenFromViz }) => { const styles = useStyles2(getStyles, justify, marginRight); const innerValueScrollStyle = showValueScroll ? { maxHeight: 55, whiteSpace: "wrap", wordBreak: "break-word", overflowY: "auto" } : { whiteSpace: "pre-line", wordBreak: "break-word", lineHeight: 1.2 }; const [showLabelTooltip, setShowLabelTooltip] = useState(false); const [copiedText, setCopiedText] = useState(null); const [showCopySuccess, setShowCopySuccess] = useState(false); const labelRef = useRef(null); const valueRef = useRef(null); useEffect(() => { let timeoutId; if (showCopySuccess) { timeoutId = setTimeout(() => { setShowCopySuccess(false); }, SHOW_SUCCESS_DURATION); } return () => { window.clearTimeout(timeoutId); }; }, [showCopySuccess]); const copyToClipboard = async (text, type) => { if (!CAN_COPY) { fallbackCopyToClipboard(text, type); return; } try { await navigator.clipboard.writeText(text); setCopiedText({ [`${type}`]: text }); setShowCopySuccess(true); } catch (error) { setCopiedText(null); } }; const fallbackCopyToClipboard = (text, type) => { var _a; const textarea = document.createElement("textarea"); (_a = labelRef.current) == null ? void 0 : _a.appendChild(textarea); textarea.value = text; textarea.focus(); textarea.select(); try { const successful = document.execCommand("copy"); if (successful) { setCopiedText({ [`${type}`]: text }); setShowCopySuccess(true); } } catch (err) { console.error("Unable to copy to clipboard", err); } textarea.remove(); }; const onMouseEnterLabel = (event) => { if (event.currentTarget.offsetWidth < event.currentTarget.scrollWidth) { setShowLabelTooltip(true); } }; const onMouseLeaveLabel = () => setShowLabelTooltip(false); if (label.length * HORIZONTAL_PX_PER_CHAR > window.innerWidth / 2) { label = label.replaceAll("{", "{\n ").replaceAll("}", "\n}").replaceAll(", ", ",\n "); } return /* @__PURE__ */ jsxs("div", { className: styles.contentWrapper, children: [ color && colorPlacement === VizTooltipColorPlacement.first && /* @__PURE__ */ jsx("div", { className: styles.colorWrapper, children: /* @__PURE__ */ jsx( VizTooltipColorIndicator, { color, colorIndicator, lineStyle, isHollow: isHiddenFromViz } ) }), label && /* @__PURE__ */ jsx("div", { className: styles.labelWrapper, children: !isPinned ? /* @__PURE__ */ jsx("div", { className: clsx(styles.label, isActive ? styles.activeSeries : ""), children: label }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Tooltip, { content: label, interactive: false, show: showLabelTooltip, children: /* @__PURE__ */ jsxs(Fragment, { children: [ showCopySuccess && (copiedText == null ? void 0 : copiedText.label) && /* @__PURE__ */ jsx(InlineToast, { placement: "top", referenceElement: labelRef.current, children: SUCCESSFULLY_COPIED_TEXT }), /* @__PURE__ */ jsx( "div", { className: clsx(styles.label, isActive ? styles.activeSeries : "", CAN_COPY ? styles.copy : ""), onMouseEnter: onMouseEnterLabel, onMouseLeave: onMouseLeaveLabel, onClick: () => copyToClipboard(label, "label" /* label */), ref: labelRef, children: label } ) ] }) }) }) }), /* @__PURE__ */ jsxs("div", { className: styles.valueWrapper, children: [ color && colorPlacement === VizTooltipColorPlacement.leading && /* @__PURE__ */ jsx( VizTooltipColorIndicator, { color, colorIndicator, position: ColorIndicatorPosition.Leading, lineStyle } ), !isPinned ? /* @__PURE__ */ jsx("div", { className: styles.value, style: innerValueScrollStyle, children: value }) : /* @__PURE__ */ jsxs(Fragment, { children: [ showCopySuccess && (copiedText == null ? void 0 : copiedText.value) && /* @__PURE__ */ jsx(InlineToast, { placement: "top", referenceElement: valueRef.current, children: SUCCESSFULLY_COPIED_TEXT }), /* @__PURE__ */ jsx( "div", { className: clsx(styles.value, CAN_COPY ? styles.copy : ""), style: innerValueScrollStyle, onClick: () => copyToClipboard(value ? value.toString() : "", "value" /* value */), ref: valueRef, children: value } ) ] }), color && colorPlacement === VizTooltipColorPlacement.trailing && /* @__PURE__ */ jsx( VizTooltipColorIndicator, { color, colorIndicator, position: ColorIndicatorPosition.Trailing, lineStyle } ) ] }) ] }); }; const getStyles = (theme, justify = "start", marginRight) => ({ contentWrapper: css({ display: "flex", maxWidth: "100%", alignItems: "start", justifyContent: justify, columnGap: theme.spacing(0.75) }), label: css({ display: "inline" }), value: css({ fontWeight: 500, textOverflow: "ellipsis", overflow: "hidden" }), colorWrapper: css({ alignSelf: "center", flexShrink: 0 }), labelWrapper: css({ flexGrow: 1, overflow: "hidden", textOverflow: "ellipsis", color: theme.colors.text.secondary, fontWeight: 400 }), valueWrapper: css({ display: "flex", alignItems: "center", flexShrink: 0, alignSelf: "center", marginRight }), activeSeries: css({ fontWeight: theme.typography.fontWeightBold, color: theme.colors.text.maxContrast }), copy: css({ cursor: "pointer" }) }); export { VizTooltipRow }; //# sourceMappingURL=VizTooltipRow.mjs.map