diff --git a/client/web/src/views/ChartViewContent/annotation/Label.tsx b/client/web/src/views/ChartViewContent/annotation/Label.tsx index a610add5de883..623ab5dceaf70 100644 --- a/client/web/src/views/ChartViewContent/annotation/Label.tsx +++ b/client/web/src/views/ChartViewContent/annotation/Label.tsx @@ -1,13 +1,16 @@ -// This component is a fork of Lable component from @visx/annotaion package -// Replace this component by original when https://github.com/airbnb/visx/issues/1126 will be resolved +// This component is a fork of Label component from @visx/annotaion package +// Replace this component by original when https://github.com/airbnb/visx/issues/1111 will be resolved import { AnnotationContext } from '@visx/annotation' import Group from '@visx/group/lib/Group' -import Text, { TextProps } from '@visx/text/lib/Text' -import classnames from 'classnames' +import { useText } from '@visx/text' +import { TextProps as OriginTextProps } from '@visx/text/lib/Text' +import classname from 'classnames' import React, { ReactElement, useContext, useMemo } from 'react' import useMeasure, { Options as UseMeasureOptions } from 'react-use-measure' +import { Text, TextProps } from './Text' + export interface LabelProps { /** Stroke color of anchor line. */ anchorLineStroke?: string @@ -51,6 +54,8 @@ export interface LabelProps { verticalAnchor?: TextProps['verticalAnchor'] /** Width of annotation, including background, for text wrapping. */ width?: number + /** Max width of annotation, including background, for text wrapping. */ + maxWidth?: number /** Left offset of entire AnnotationLabel, if not specified uses x + dx from Annotation. */ x?: number /** Top offset of entire AnnotationLabel, if not specified uses y + dy from Annotation. */ @@ -91,6 +96,7 @@ export function Label({ titleProps, verticalAnchor: propsVerticalAnchor, width: propertyWidth, + maxWidth = 125, x: propsX, y: propsY, }: LabelProps): ReactElement | null { @@ -105,9 +111,45 @@ export function Label({ const { x = 0, y = 0, dx = 0, dy = 0 } = useContext(AnnotationContext) const height = Math.floor(padding.top + padding.bottom + (titleBounds.height ?? 0) + (subtitleBounds.height ?? 0)) - const measuredWidth = padding.right + padding.left + Math.max(titleBounds.width ?? 0, subtitleBounds.width ?? 0) + const { wordsByLines: titleWordsByLine } = useText({ + children: title, + verticalAnchor: 'start', + capHeight: titleFontSize, + width: maxWidth, + style: { + fontSize: `${titleFontSize}px`, + fontWeight: titleFontWeight as any, + }, + ...(titleProps as OriginTextProps), + }) + + const { wordsByLines: subtitleWordsByLine } = useText({ + children: subtitle, + verticalAnchor: 'start', + capHeight: subtitleFontSize, + width: maxWidth, + style: { + fontSize: `${subtitleFontSize}px`, + fontWeight: subtitleFontWeight as any, + // fontFamily: subtitleProps?.fontFamily, + }, + ...(subtitleProps as OriginTextProps), + }) + + const titleMeasuredWidth = titleWordsByLine.reduce( + (maxTitleWidth, line) => Math.max(maxTitleWidth, line.width ?? 0), + 0 + ) + + const subtitleMeasuredWidth = subtitleWordsByLine.reduce( + (maxSubtitleWidth, line) => Math.max(maxSubtitleWidth, line.width ?? 0), + 0 + ) + + const textMeasuredWidth = Math.ceil(Math.min(maxWidth, Math.max(titleMeasuredWidth, subtitleMeasuredWidth))) + const measuredWidth = padding.right + padding.left + textMeasuredWidth const width = propertyWidth ?? measuredWidth - const innerWidth = (width ?? measuredWidth) - padding.left - padding.right + const innerWidth = width - padding.left - padding.right // offset container position based on horizontal + vertical anchor const horizontalAnchor = @@ -163,7 +205,7 @@ export function Label({ top={containerCoords.y} left={containerCoords.x} pointerEvents="none" - className={classnames('visx-annotationlabel', className)} + className={classname('visx-annotationlabel', className)} opacity={titleBounds.height === 0 && subtitleBounds.height === 0 ? 0 : 1} > {showBackground && ( diff --git a/client/web/src/views/ChartViewContent/annotation/Text.tsx b/client/web/src/views/ChartViewContent/annotation/Text.tsx new file mode 100644 index 0000000000000..72d20579afe14 --- /dev/null +++ b/client/web/src/views/ChartViewContent/annotation/Text.tsx @@ -0,0 +1,56 @@ +/** + * Forked component from @visx/text package. + * Removed https://github.com/airbnb/visx/issues/1111 when will be resolved + * */ +import { useText, TextProps as OriginTextProps } from '@visx/text' +import React, { ReactElement } from 'react' + +const SVG_STYLE = { overflow: 'visible' } + +/** + * Origin text props with changed innerRef is equal to ref of text element + * origin value = ref of svg element. Because firefox has bug with measurements + * nested svg element without sizes we have to measure sizes of text element instead. + * */ +export interface TextProps extends Omit { + /** Ref access to text element */ + innerRef?: React.Ref +} + +/** + * Displays svg text element. + * */ +export function Text(props: TextProps): ReactElement { + const { + dx: xCoord = 0, + dy: yCoord = 0, + textAnchor = 'start', + innerRef, + verticalAnchor, + angle, + lineHeight = '1em', + scaleToFit = false, + capHeight, + width, + ...textProps + } = props + + // eslint-disable-next-line id-length + const { x = 0, fontSize } = textProps + const { wordsByLines, startDy, transform } = useText(props as OriginTextProps) + + return ( + // eslint-disable-next-line react/forbid-dom-props + + {wordsByLines.length > 0 ? ( + + {wordsByLines.map((line, index) => ( + + {line.words.join(' ')} + + ))} + + ) : null} + + ) +} diff --git a/client/web/src/views/ChartViewContent/charts/pie/components/PieArc.tsx b/client/web/src/views/ChartViewContent/charts/pie/components/PieArc.tsx index 544eb16eb2054..d758b871e7095 100644 --- a/client/web/src/views/ChartViewContent/charts/pie/components/PieArc.tsx +++ b/client/web/src/views/ChartViewContent/charts/pie/components/PieArc.tsx @@ -91,6 +91,8 @@ export function PieArc(props: PieArcProps): ReactElement { showAnchorLine={false} title={name} subtitleDy={0} + titleFontWeight={200} + subtitleFontWeight={200} titleProps={TITLE_PROPS} subtitleProps={SUBTITLE_PROPS} subtitle={labelSubtitle}