Skip to content

Commit e61bf3d

Browse files
committed
chore: Add forward ref to all relevant components (#1294)
1 parent 10aa9f9 commit e61bf3d

File tree

16 files changed

+193
-152
lines changed

16 files changed

+193
-152
lines changed

packages/body/src/body.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
import * as React from "react";
22

3+
type BodyElement = React.ElementRef<"body">;
34
type RootProps = React.ComponentPropsWithoutRef<"body">;
45

56
export type BodyProps = RootProps;
67

7-
export const Body: React.FC<Readonly<BodyProps>> = ({
8-
children,
9-
style,
10-
...props
11-
}) => {
12-
return (
13-
<body {...props} style={style}>
14-
{children}
15-
</body>
16-
);
17-
};
8+
export const Body = React.forwardRef<BodyElement, Readonly<BodyProps>>(
9+
({ children, style, ...props }, ref) => {
10+
return (
11+
<body {...props} ref={ref} style={style}>
12+
{children}
13+
</body>
14+
);
15+
},
16+
);
1817

1918
Body.displayName = "Body";

packages/button/src/button.tsx

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,46 @@
11
import * as React from "react";
22
import { parsePadding, pxToPt } from "./utils";
33

4+
type ButtonElement = React.ElementRef<"a">;
45
export type ButtonProps = React.ComponentPropsWithoutRef<"a">;
56

6-
export const Button: React.FC<Readonly<ButtonProps>> = ({
7-
children,
8-
style,
9-
target = "_blank",
10-
...props
11-
}) => {
12-
const { pt, pr, pb, pl } = parsePadding({
13-
padding: style?.padding,
14-
paddingLeft: style?.paddingLeft,
15-
paddingRight: style?.paddingRight,
16-
paddingTop: style?.paddingTop,
17-
paddingBottom: style?.paddingBottom,
18-
});
7+
export const Button = React.forwardRef<ButtonElement, Readonly<ButtonProps>>(
8+
({ children, style, target = "_blank", ...props }, ref) => {
9+
const { pt, pr, pb, pl } = parsePadding({
10+
padding: style?.padding,
11+
paddingLeft: style?.paddingLeft,
12+
paddingRight: style?.paddingRight,
13+
paddingTop: style?.paddingTop,
14+
paddingBottom: style?.paddingBottom,
15+
});
1916

20-
const y = pt + pb;
21-
const textRaise = pxToPt(y);
17+
const y = pt + pb;
18+
const textRaise = pxToPt(y);
2219

23-
return (
24-
<a
25-
{...props}
26-
style={buttonStyle({ ...style, pt, pr, pb, pl })}
27-
target={target}
28-
>
29-
<span
30-
dangerouslySetInnerHTML={{
31-
__html: `<!--[if mso]><i style="letter-spacing: ${pl}px;mso-font-width:-100%;mso-text-raise:${textRaise}" hidden>&nbsp;</i><![endif]-->`,
32-
}}
33-
/>
34-
<span style={buttonTextStyle(pb)}>{children}</span>
35-
<span
36-
dangerouslySetInnerHTML={{
37-
__html: `<!--[if mso]><i style="letter-spacing: ${pr}px;mso-font-width:-100%" hidden>&nbsp;</i><![endif]-->`,
38-
}}
39-
/>
40-
</a>
41-
);
42-
};
20+
return (
21+
<a
22+
{...props}
23+
ref={ref}
24+
style={buttonStyle({ ...style, pt, pr, pb, pl })}
25+
target={target}
26+
>
27+
<span
28+
dangerouslySetInnerHTML={{
29+
__html: `<!--[if mso]><i style="letter-spacing: ${pl}px;mso-font-width:-100%;mso-text-raise:${textRaise}" hidden>&nbsp;</i><![endif]-->`,
30+
}}
31+
/>
32+
<span style={buttonTextStyle(pb)}>{children}</span>
33+
<span
34+
dangerouslySetInnerHTML={{
35+
__html: `<!--[if mso]><i style="letter-spacing: ${pr}px;mso-font-width:-100%" hidden>&nbsp;</i><![endif]-->`,
36+
}}
37+
/>
38+
</a>
39+
);
40+
},
41+
);
42+
43+
Button.displayName = "Button";
4344

4445
const buttonStyle = (
4546
style?: React.CSSProperties & {

packages/code-block/src/code-block.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ const CodeBlockLine = ({
6868
/**
6969
* A component to show code using prismjs.
7070
*/
71-
export const CodeBlock: React.FC<CodeBlockProps> = (props) => {
71+
export const CodeBlock = React.forwardRef<
72+
React.ElementRef<"pre">,
73+
CodeBlockProps
74+
>((props, ref) => {
7275
const languageGrammar = Prism.languages[props.language];
7376
if (typeof languageGrammar === "undefined")
7477
throw new Error(
@@ -82,11 +85,8 @@ export const CodeBlock: React.FC<CodeBlockProps> = (props) => {
8285

8386
return (
8487
<pre
85-
style={{
86-
...props.theme.base,
87-
width: "100%",
88-
...props.style,
89-
}}
88+
ref={ref}
89+
style={{ ...props.theme.base, width: "100%", ...props.style }}
9090
>
9191
<code>
9292
{tokensPerLine.map((tokensForLine, lineIndex) => (
@@ -108,4 +108,6 @@ export const CodeBlock: React.FC<CodeBlockProps> = (props) => {
108108
</code>
109109
</pre>
110110
);
111-
};
111+
});
112+
113+
CodeBlock.displayName = "CodeBlock";

packages/code-inline/src/code-inline.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1+
import React from "react";
2+
13
type RootProps = React.ComponentPropsWithoutRef<"code"> &
24
React.ComponentPropsWithoutRef<"span">;
35

6+
type SpanElement = React.ElementRef<"span">;
47
export type CodeInlineProps = RootProps;
58

69
/**
710
* If you are sending emails for users that have the Orange.fr email client,
811
* beware that this component will only work when you have a head containing meta tags.
912
*/
10-
export const CodeInline: React.FC<Readonly<CodeInlineProps>> = ({
11-
children,
12-
...props
13-
}) => {
13+
export const CodeInline = React.forwardRef<
14+
SpanElement,
15+
Readonly<CodeInlineProps>
16+
>(({ children, ...props }, ref) => {
1417
return (
1518
<>
1619
{/*
@@ -45,10 +48,13 @@ export const CodeInline: React.FC<Readonly<CodeInlineProps>> = ({
4548
<span
4649
{...props}
4750
className={`${props.className ? props.className : ""} cio`}
51+
ref={ref}
4852
style={{ display: "none", ...props.style }}
4953
>
5054
{children}
5155
</span>
5256
</>
5357
);
54-
};
58+
});
59+
60+
CodeInline.displayName = "CodeInline";

packages/column/src/column.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import * as React from "react";
22

33
type RootProps = React.ComponentPropsWithoutRef<"td">;
4+
type TdElement = React.ElementRef<"td">;
45

56
export type ColumnProps = RootProps;
67

7-
export const Column: React.FC<Readonly<ColumnProps>> = ({
8-
children,
9-
style,
10-
...props
11-
}) => {
12-
return (
13-
<td {...props} data-id="__react-email-column" style={style}>
14-
{children}
15-
</td>
16-
);
17-
};
8+
export const Column = React.forwardRef<TdElement, Readonly<ColumnProps>>(
9+
({ children, style, ...props }, ref) => {
10+
return (
11+
<td {...props} data-id="__react-email-column" ref={ref} style={style}>
12+
{children}
13+
</td>
14+
);
15+
},
16+
);
17+
18+
Column.displayName = "Column";

packages/container/src/container.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import * as React from "react";
22

33
type RootProps = React.ComponentPropsWithoutRef<"table">;
4+
type TableElement = React.ElementRef<"table">;
45

56
export type ContainerProps = RootProps;
67

7-
export const Container: React.FC<Readonly<ContainerProps>> = ({
8-
children,
9-
style,
10-
...props
11-
}) => {
8+
export const Container = React.forwardRef<
9+
TableElement,
10+
Readonly<ContainerProps>
11+
>(({ children, style, ...props }, ref) => {
1212
return (
1313
<table
1414
align="center"
@@ -17,6 +17,7 @@ export const Container: React.FC<Readonly<ContainerProps>> = ({
1717
border={0}
1818
cellPadding="0"
1919
cellSpacing="0"
20+
ref={ref}
2021
role="presentation"
2122
style={{ maxWidth: "37.5em", ...style }}
2223
>
@@ -27,4 +28,6 @@ export const Container: React.FC<Readonly<ContainerProps>> = ({
2728
</tbody>
2829
</table>
2930
);
30-
};
31+
});
32+
33+
Container.displayName = "Container";

packages/head/src/head.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
import * as React from "react";
22

33
type RootProps = React.ComponentPropsWithoutRef<"head">;
4+
type HeadElement = React.ElementRef<"head">;
45

56
export type HeadProps = RootProps;
67

7-
export const Head: React.FC<Readonly<HeadProps>> = ({ children, ...props }) => (
8-
<head {...props}>
9-
<meta content="text/html; charset=UTF-8" httpEquiv="Content-Type" />
10-
<meta name="x-apple-disable-message-reformatting" />
11-
{children}
12-
</head>
8+
export const Head = React.forwardRef<HeadElement, Readonly<HeadProps>>(
9+
({ children, ...props }, ref) => (
10+
<head {...props} ref={ref}>
11+
<meta content="text/html; charset=UTF-8" httpEquiv="Content-Type" />
12+
<meta name="x-apple-disable-message-reformatting" />
13+
{children}
14+
</head>
15+
),
1316
);
17+
18+
Head.displayName = "Head";

packages/hr/src/hr.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@ type RootProps = React.ComponentPropsWithoutRef<"hr">;
44

55
export type HrProps = RootProps;
66

7-
export const Hr: React.FC<Readonly<HrProps>> = ({ style, ...props }) => (
8-
<hr
9-
{...props}
10-
style={{
11-
width: "100%",
12-
border: "none",
13-
borderTop: "1px solid #eaeaea",
14-
...style,
15-
}}
16-
/>
7+
export const Hr = React.forwardRef<React.ElementRef<"hr">, Readonly<HrProps>>(
8+
({ style, ...props }, ref) => (
9+
<hr
10+
{...props}
11+
ref={ref}
12+
style={{
13+
width: "100%",
14+
border: "none",
15+
borderTop: "1px solid #eaeaea",
16+
...style,
17+
}}
18+
/>
19+
),
1720
);
21+
22+
Hr.displayName = "Hr";

packages/html/src/html.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ type RootProps = React.ComponentPropsWithoutRef<"html">;
44

55
export type HtmlProps = RootProps;
66

7-
export const Html: React.FC<Readonly<HtmlProps>> = ({
8-
children,
9-
lang = "en",
10-
dir = "ltr",
11-
...props
12-
}) => (
13-
<html {...props} dir={dir} lang={lang}>
7+
export const Html = React.forwardRef<
8+
React.ElementRef<"html">,
9+
Readonly<HtmlProps>
10+
>(({ children, lang = "en", dir = "ltr", ...props }, ref) => (
11+
<html {...props} dir={dir} lang={lang} ref={ref}>
1412
{children}
1513
</html>
16-
);
14+
));
15+
16+
Html.displayName = "Html";

packages/img/src/img.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@ type RootProps = React.ComponentPropsWithoutRef<"img">;
44

55
export type ImgProps = RootProps;
66

7-
export const Img: React.FC<Readonly<ImgProps>> = ({
8-
alt,
9-
src,
10-
width,
11-
height,
12-
style,
13-
...props
14-
}) => (
7+
export const Img = React.forwardRef<
8+
React.ElementRef<"img">,
9+
Readonly<ImgProps>
10+
>(({ alt, src, width, height, style, ...props }, ref) => (
1511
<img
1612
{...props}
1713
alt={alt}
1814
height={height}
15+
ref={ref}
1916
src={src}
2017
style={{
2118
display: "block",
@@ -26,4 +23,6 @@ export const Img: React.FC<Readonly<ImgProps>> = ({
2623
}}
2724
width={width}
2825
/>
29-
);
26+
));
27+
28+
Img.displayName = "Img";

packages/link/src/link.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ type RootProps = React.ComponentPropsWithoutRef<"a">;
44

55
export type LinkProps = RootProps;
66

7-
export const Link: React.FC<Readonly<LinkProps>> = ({
8-
target = "_blank",
9-
style,
10-
...props
11-
}) => (
7+
export const Link = React.forwardRef<
8+
React.ElementRef<"a">,
9+
Readonly<LinkProps>
10+
>(({ target = "_blank", style, ...props }, ref) => (
1211
<a
1312
{...props}
13+
ref={ref}
1414
style={{
1515
color: "#067df7",
1616
textDecoration: "none",
@@ -20,4 +20,6 @@ export const Link: React.FC<Readonly<LinkProps>> = ({
2020
>
2121
{props.children}
2222
</a>
23-
);
23+
));
24+
25+
Link.displayName = "Link";

0 commit comments

Comments
 (0)