-
Notifications
You must be signed in to change notification settings - Fork 715
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
minor fix to <Text> and re-enable unit tests. #790
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,15 @@ function isNumber(val: unknown): val is number { | |
return typeof val === 'number'; | ||
} | ||
|
||
function isValidXOrY(xOrY: string | number | undefined) { | ||
return ( | ||
// number that is not NaN or Infinity | ||
(typeof xOrY === 'number' && Number.isFinite(xOrY)) || | ||
// for percentage | ||
typeof xOrY === 'string' | ||
); | ||
} | ||
|
||
interface WordWithWidth { | ||
word: string; | ||
width: number; | ||
|
@@ -24,7 +33,7 @@ type SVGTextProps = React.SVGAttributes<SVGTextElement>; | |
type OwnProps = { | ||
/** className to apply to the SVGText element. */ | ||
className?: string; | ||
/** Whether to scale the fontSize to accomodate the specified width. */ | ||
/** Whether to scale the fontSize to accommodate the specified width. */ | ||
scaleToFit?: boolean; | ||
/** Rotational angle of the text. */ | ||
angle?: number; | ||
|
@@ -176,6 +185,11 @@ class Text extends React.Component<TextProps, TextState> { | |
const { wordsByLines } = this.state; | ||
const { x, y } = textProps; | ||
|
||
// Cannot render <text> if x or y is invalid | ||
if (!isValidXOrY(x) || !isValidXOrY(y)) { | ||
return <svg ref={innerRef} x={dx} y={dy} fontSize={textProps.fontSize} style={SVG_STYLE} />; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you think we should return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about return null but think if at least having the svg may keep the layout from changing if consumer depends on having some element there. |
||
} | ||
|
||
let startDy: string | undefined; | ||
if (verticalAnchor === 'start') { | ||
startDy = reduceCSSCalc(`calc(${capHeight})`); | ||
|
@@ -187,7 +201,6 @@ class Text extends React.Component<TextProps, TextState> { | |
startDy = reduceCSSCalc(`calc(${wordsByLines.length - 1} * -${lineHeight})`); | ||
} | ||
|
||
let transform: string | undefined; | ||
const transforms = []; | ||
if (isNumber(x) && isNumber(y) && isNumber(width) && scaleToFit && wordsByLines.length > 0) { | ||
const lineWidth = wordsByLines[0].width || 1; | ||
|
@@ -200,9 +213,8 @@ class Text extends React.Component<TextProps, TextState> { | |
if (angle) { | ||
transforms.push(`rotate(${angle}, ${x}, ${y})`); | ||
} | ||
if (transforms.length > 0) { | ||
transform = transforms.join(' '); | ||
} | ||
|
||
const transform = transforms.length > 0 ? transforms.join(' ') : undefined; | ||
|
||
return ( | ||
<svg ref={innerRef} x={dx} y={dy} fontSize={textProps.fontSize} style={SVG_STYLE}> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// @ts-ignore | ||
let originalFn: typeof SVGElement.prototype.getComputedTextLength; | ||
|
||
/** | ||
* JSDom does not implement getComputedTextLength() | ||
* so this function add mock implementation for testing. | ||
*/ | ||
export function addMock() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! |
||
// @ts-ignore | ||
originalFn = SVGElement.prototype.getComputedTextLength; | ||
|
||
// @ts-ignore | ||
SVGElement.prototype.getComputedTextLength = function getComputedTextLength() { | ||
// Make every character 10px wide | ||
return (this.textContent?.length ?? 0) * 10; | ||
}; | ||
} | ||
|
||
/** | ||
* Remove mock from addMock() | ||
*/ | ||
export function removeMock() { | ||
// @ts-ignore | ||
SVGElement.prototype.getComputedTextLength = originalFn; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we actually need this because we have a babel plugin that adds proptypes based on the types defined for a component.
this is useful for consumers I think (proptypes complain in dev / in the console), but @hshoff also was surprised by this recently so maybe we could consider removing it througout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok!