|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
import { css, cx } from '@emotion/css'; |
|
|
|
|
import React, { ReactNode, useEffect, useRef, useState } from 'react'; |
|
|
|
|
import React, { CSSProperties, ReactNode, useEffect, useRef, useState } from 'react'; |
|
|
|
|
|
|
|
|
|
import { GrafanaTheme2 } from '@grafana/data'; |
|
|
|
|
|
|
|
|
@ -16,6 +16,7 @@ interface VizTooltipRowProps extends Omit<VizTooltipItem, 'value'> { |
|
|
|
|
isActive?: boolean; // for series list
|
|
|
|
|
marginRight?: string; |
|
|
|
|
isPinned: boolean; |
|
|
|
|
showValueScroll?: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum LabelValueTypes { |
|
|
|
@ -37,11 +38,23 @@ export const VizTooltipRow = ({ |
|
|
|
|
marginRight = '0px', |
|
|
|
|
isPinned, |
|
|
|
|
lineStyle, |
|
|
|
|
showValueScroll, |
|
|
|
|
}: VizTooltipRowProps) => { |
|
|
|
|
const styles = useStyles2(getStyles, justify, marginRight); |
|
|
|
|
|
|
|
|
|
const innerValueScrollStyle: CSSProperties = showValueScroll |
|
|
|
|
? { |
|
|
|
|
maxHeight: 55, |
|
|
|
|
whiteSpace: 'wrap', |
|
|
|
|
wordBreak: 'break-word', |
|
|
|
|
overflowY: 'scroll', |
|
|
|
|
} |
|
|
|
|
: { |
|
|
|
|
whiteSpace: 'wrap', |
|
|
|
|
wordBreak: 'break-word', |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const [showLabelTooltip, setShowLabelTooltip] = useState(false); |
|
|
|
|
const [showValueTooltip, setShowValueTooltip] = useState(false); |
|
|
|
|
|
|
|
|
|
const [copiedText, setCopiedText] = useState<Record<string, string> | null>(null); |
|
|
|
|
const [showCopySuccess, setShowCopySuccess] = useState(false); |
|
|
|
@ -106,14 +119,6 @@ export const VizTooltipRow = ({ |
|
|
|
|
|
|
|
|
|
const onMouseLeaveLabel = () => setShowLabelTooltip(false); |
|
|
|
|
|
|
|
|
|
const onMouseEnterValue = (event: React.MouseEvent<HTMLDivElement>) => { |
|
|
|
|
if (event.currentTarget.offsetWidth < event.currentTarget.scrollWidth) { |
|
|
|
|
setShowValueTooltip(true); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const onMouseLeaveValue = () => setShowValueTooltip(false); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div className={styles.contentWrapper}> |
|
|
|
|
{(color || label) && ( |
|
|
|
@ -160,27 +165,26 @@ export const VizTooltipRow = ({ |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
{!isPinned ? ( |
|
|
|
|
<div className={cx(styles.value, isActive)}>{value}</div> |
|
|
|
|
<div className={cx(styles.value, isActive)} style={innerValueScrollStyle}> |
|
|
|
|
{value} |
|
|
|
|
</div> |
|
|
|
|
) : ( |
|
|
|
|
<Tooltip content={value ? value.toString() : ''} interactive={false} show={showValueTooltip}> |
|
|
|
|
<> |
|
|
|
|
{showCopySuccess && copiedText?.value && ( |
|
|
|
|
<InlineToast placement="top" referenceElement={valueRef.current}> |
|
|
|
|
{SUCCESSFULLY_COPIED_TEXT} |
|
|
|
|
</InlineToast> |
|
|
|
|
)} |
|
|
|
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */} |
|
|
|
|
<div |
|
|
|
|
className={cx(styles.value, isActive, navigator?.clipboard && styles.copy)} |
|
|
|
|
onMouseEnter={onMouseEnterValue} |
|
|
|
|
onMouseLeave={onMouseLeaveValue} |
|
|
|
|
onClick={() => copyToClipboard(value ? value.toString() : '', LabelValueTypes.value)} |
|
|
|
|
ref={valueRef} |
|
|
|
|
> |
|
|
|
|
{value} |
|
|
|
|
</div> |
|
|
|
|
</> |
|
|
|
|
</Tooltip> |
|
|
|
|
<> |
|
|
|
|
{showCopySuccess && copiedText?.value && ( |
|
|
|
|
<InlineToast placement="top" referenceElement={valueRef.current}> |
|
|
|
|
{SUCCESSFULLY_COPIED_TEXT} |
|
|
|
|
</InlineToast> |
|
|
|
|
)} |
|
|
|
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */} |
|
|
|
|
<div |
|
|
|
|
className={cx(styles.value, isActive, navigator?.clipboard && styles.copy)} |
|
|
|
|
style={innerValueScrollStyle} |
|
|
|
|
onClick={() => copyToClipboard(value ? value.toString() : '', LabelValueTypes.value)} |
|
|
|
|
ref={valueRef} |
|
|
|
|
> |
|
|
|
|
{value} |
|
|
|
|
</div> |
|
|
|
|
</> |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
{color && colorPlacement === ColorPlacement.trailing && ( |
|
|
|
@ -199,9 +203,8 @@ export const VizTooltipRow = ({ |
|
|
|
|
const getStyles = (theme: GrafanaTheme2, justify: string, marginRight: string) => ({ |
|
|
|
|
contentWrapper: css({ |
|
|
|
|
display: 'flex', |
|
|
|
|
alignItems: 'center', |
|
|
|
|
alignItems: 'start', |
|
|
|
|
justifyContent: justify, |
|
|
|
|
flexWrap: 'wrap', |
|
|
|
|
marginRight: marginRight, |
|
|
|
|
}), |
|
|
|
|
label: css({ |
|
|
|
@ -219,7 +222,6 @@ const getStyles = (theme: GrafanaTheme2, justify: string, marginRight: string) = |
|
|
|
|
valueWrapper: css({ |
|
|
|
|
display: 'flex', |
|
|
|
|
alignItems: 'center', |
|
|
|
|
minWidth: 0, |
|
|
|
|
}), |
|
|
|
|
activeSeries: css({ |
|
|
|
|
fontWeight: theme.typography.fontWeightBold, |
|
|
|
|