diff --git a/packages/visx-text/src/Text.tsx b/packages/visx-text/src/Text.tsx index a3683a8c0..2dfa86ba2 100644 --- a/packages/visx-text/src/Text.tsx +++ b/packages/visx-text/src/Text.tsx @@ -1,5 +1,6 @@ import React from 'react'; import reduceCSSCalc from 'reduce-css-calc'; +import uniqueId from 'lodash/uniqueId'; import getStringWidth from './util/getStringWidth'; const SVG_STYLE = { overflow: 'visible' }; @@ -67,12 +68,15 @@ type OwnProps = { width?: number; /** String (or number coercible to one) to be styled and positioned. */ children?: string | number; + /** Path for the text to follow along. */ + textPath?: string; }; export type TextProps = OwnProps & Omit; type TextState = { wordsByLines: WordsWithWidth[]; + textPathId: string; }; class Text extends React.Component { @@ -88,14 +92,18 @@ class Text extends React.Component { verticalAnchor: 'end', // default SVG behavior }; - state: TextState = { - wordsByLines: [], - }; - private wordsWithWidth: WordWithWidth[] = []; - private spaceWidth: number = 0; + constructor(props: TextProps) { + super(props); + + this.state = { + wordsByLines: [], + textPathId: props.textPath ? uniqueId('text-path-') : '', + }; + } + componentDidMount() { this.updateWordsByLines(this.props, true); } @@ -178,10 +186,11 @@ class Text extends React.Component { capHeight, innerRef, width, + textPath, ...textProps } = this.props; - const { wordsByLines } = this.state; + const { wordsByLines, textPathId } = this.state; const { x, y } = textProps; // Cannot render if x or y is invalid @@ -214,15 +223,17 @@ class Text extends React.Component { } const transform = transforms.length > 0 ? transforms.join(' ') : undefined; + const text = wordsByLines.map((line, index) => ( + + {line.words.join(' ')} + + )); return ( + {textPath && } - {wordsByLines.map((line, index) => ( - - {line.words.join(' ')} - - ))} + {textPath ? {text} : text} ); diff --git a/packages/visx-text/test/Text.test.tsx b/packages/visx-text/test/Text.test.tsx index 6eb9d1e07..db7894be3 100644 --- a/packages/visx-text/test/Text.test.tsx +++ b/packages/visx-text/test/Text.test.tsx @@ -162,4 +162,23 @@ describe('', () => { wrapper.setProps({ verticalAnchor: 'start' }); expect(getVerticalOffset(wrapper)).toBe('0.71em'); }); + it('Should render textPath when textPath is passed', () => { + const wrapper = mount(Text path test); + + const textPath = wrapper.find('textPath'); + const path = wrapper.find('path'); + + expect(textPath).toHaveLength(1); + expect(path).toHaveLength(1); + + expect(textPath.props().href).toEqual(`#${path.props().id}`); + expect(path.props().d).toEqual('M10 10'); + }); + + it('Should not render textPath when textPath is not passed', () => { + const wrapper = mount(Text path test); + + expect(wrapper.find('textPath')).toHaveLength(0); + expect(wrapper.find('path')).toHaveLength(0); + }); });