react-email 1.4.2-canary.0 → 1.4.2-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.react-email/next-env.d.ts +0 -0
- package/.react-email/package.json +0 -0
- package/.react-email/postcss.config.js +0 -0
- package/.react-email/src/components/button.tsx +0 -0
- package/.react-email/src/components/code.tsx +0 -0
- package/.react-email/src/components/heading.tsx +0 -0
- package/.react-email/src/components/icon-base.tsx +0 -0
- package/.react-email/src/components/icon-button.tsx +0 -0
- package/.react-email/src/components/icon-check.tsx +0 -0
- package/.react-email/src/components/icon-clipboard.tsx +0 -0
- package/.react-email/src/components/icon-download.tsx +0 -0
- package/.react-email/src/components/index.ts +0 -0
- package/.react-email/src/components/layout.tsx +0 -0
- package/.react-email/src/components/logo.tsx +0 -0
- package/.react-email/src/components/send.tsx +0 -0
- package/.react-email/src/components/sidebar.tsx +0 -0
- package/.react-email/src/components/text.tsx +0 -0
- package/.react-email/src/components/tooltip-content.tsx +0 -0
- package/.react-email/src/components/tooltip.tsx +0 -0
- package/.react-email/src/components/topbar.tsx +0 -0
- package/.react-email/src/pages/_app.tsx +26 -0
- package/.react-email/src/pages/_document.tsx +0 -0
- package/.react-email/src/pages/index.tsx +0 -0
- package/.react-email/src/styles/globals.css +0 -0
- package/.react-email/src/utils/as.ts +0 -0
- package/.react-email/src/utils/copy-text-to-clipboard.ts +0 -0
- package/.react-email/src/utils/index.ts +0 -0
- package/.react-email/src/utils/unreachable.ts +0 -0
- package/.react-email/tailwind.config.js +0 -0
- package/.react-email/tsconfig.json +0 -0
- package/dist/commands/dev.js +52 -41
- package/dist/commands/exportTemplates.js +20 -1
- package/dist/utils/watcher.d.ts +1 -0
- package/dist/utils/watcher.js +7 -4
- package/emails/airbnb-review.tsx +163 -0
- package/emails/dropbox-reset-password.tsx +85 -0
- package/emails/google-play-policy-update.tsx +229 -0
- package/emails/koala-welcome.tsx +97 -0
- package/emails/linear-login-code.tsx +124 -0
- package/emails/notion-magic-link.tsx +133 -0
- package/emails/plaid-verify-identity.tsx +133 -0
- package/emails/raycast-magic-link.tsx +107 -0
- package/emails/static/airbnb-logo.png +0 -0
- package/emails/static/airbnb-review-user.jpg +0 -0
- package/emails/static/chat.png +0 -0
- package/emails/static/dropbox.png +0 -0
- package/emails/static/google-play-academy.png +0 -0
- package/emails/static/google-play-chat.png +0 -0
- package/emails/static/google-play-footer.png +0 -0
- package/emails/static/google-play-header.png +0 -0
- package/emails/static/google-play-icon.png +0 -0
- package/emails/static/google-play-logo.png +0 -0
- package/emails/static/google-play-pl.png +0 -0
- package/emails/static/google-play.png +0 -0
- package/emails/static/linear-logo.png +0 -0
- package/emails/static/notion-logo.png +0 -0
- package/emails/static/plaid.png +0 -0
- package/emails/static/raycast-bg.png +0 -0
- package/emails/static/raycast-logo.png +0 -0
- package/emails/static/stripe-logo.png +0 -0
- package/emails/static/twitch-icon-facebook.png +0 -0
- package/emails/static/twitch-icon-twitter.png +0 -0
- package/emails/static/twitch-logo.png +0 -0
- package/emails/static/vercel-arrow.png +0 -0
- package/emails/static/vercel-logo.png +0 -0
- package/emails/static/yelp-footer.png +0 -0
- package/emails/static/yelp-header.png +0 -0
- package/emails/static/yelp-logo.png +0 -0
- package/emails/stripe-welcome.tsx +152 -0
- package/emails/twitch-reset-password.tsx +138 -0
- package/emails/vercel-invite-user.tsx +196 -0
- package/emails/yelp-recent-login.tsx +158 -0
- package/package.json +4 -3
- package/source/commands/dev.ts +55 -45
- package/source/commands/exportTemplates.ts +28 -1
- package/source/utils/watcher.ts +28 -24
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import '../styles/globals.css';
|
|
2
|
+
import type { AppProps } from 'next/app';
|
|
3
|
+
import { Inter } from '@next/font/google';
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import Head from 'next/head';
|
|
6
|
+
import { Tooltip } from '../components/tooltip';
|
|
7
|
+
|
|
8
|
+
export const inter = Inter({
|
|
9
|
+
subsets: ['latin'],
|
|
10
|
+
variable: '--font-inter',
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
function MyApp({ Component, pageProps }: AppProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div className={classnames(inter.variable, 'font-sans')}>
|
|
16
|
+
<Head>
|
|
17
|
+
<title>React Email</title>
|
|
18
|
+
</Head>
|
|
19
|
+
<Tooltip.Provider>
|
|
20
|
+
<Component {...pageProps} />
|
|
21
|
+
</Tooltip.Provider>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default MyApp;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/commands/dev.js
CHANGED
|
@@ -18,25 +18,31 @@ const read_pkg_1 = __importDefault(require("read-pkg"));
|
|
|
18
18
|
const shelljs_1 = __importDefault(require("shelljs"));
|
|
19
19
|
const styles_1 = require("../_preview/styles");
|
|
20
20
|
const dev = async () => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
try {
|
|
22
|
+
const hasReactEmailDirectory = (0, utils_1.checkDirectoryExist)(utils_1.REACT_EMAIL_ROOT);
|
|
23
|
+
if (hasReactEmailDirectory) {
|
|
24
|
+
const isUpToDate = await (0, utils_1.checkPackageIsUpToDate)();
|
|
25
|
+
if (isUpToDate) {
|
|
26
|
+
await Promise.all([generateEmailsPreview(), syncPkg()]);
|
|
27
|
+
await installDependencies();
|
|
28
|
+
shelljs_1.default.exec('yarn dev', { async: true });
|
|
29
|
+
(0, utils_1.watcher)();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
await fs_1.default.promises.rm(utils_1.REACT_EMAIL_ROOT, { recursive: true });
|
|
30
33
|
}
|
|
31
|
-
await
|
|
34
|
+
await createBasicStructure();
|
|
35
|
+
await createAppDirectories();
|
|
36
|
+
await createAppFiles();
|
|
37
|
+
await Promise.all([generateEmailsPreview(), syncPkg()]);
|
|
38
|
+
await installDependencies();
|
|
39
|
+
shelljs_1.default.exec('yarn dev', { async: true });
|
|
40
|
+
(0, utils_1.watcher)();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
await utils_1.watcherInstance.close();
|
|
44
|
+
shelljs_1.default.exit(1);
|
|
32
45
|
}
|
|
33
|
-
await createBasicStructure();
|
|
34
|
-
await createAppDirectories();
|
|
35
|
-
await createAppFiles();
|
|
36
|
-
await Promise.all([generateEmailsPreview(), syncPkg()]);
|
|
37
|
-
await installDependencies();
|
|
38
|
-
shelljs_1.default.exec('yarn dev', { async: true });
|
|
39
|
-
(0, utils_1.watcher)();
|
|
40
46
|
};
|
|
41
47
|
exports.dev = dev;
|
|
42
48
|
const createBasicStructure = async () => {
|
|
@@ -67,30 +73,35 @@ const createAppDirectories = async () => {
|
|
|
67
73
|
}
|
|
68
74
|
};
|
|
69
75
|
const createAppFiles = async () => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
try {
|
|
77
|
+
const creation = (appFiles, name) => {
|
|
78
|
+
return appFiles.map((file) => {
|
|
79
|
+
const location = name
|
|
80
|
+
? `${utils_1.SRC_PATH}/${name}/${file.title}`
|
|
81
|
+
: `${utils_1.REACT_EMAIL_ROOT}/${file.title}`;
|
|
82
|
+
return fs_1.default.promises.writeFile(location, file.content);
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
const pageCreation = pages_1.pages.map((page) => {
|
|
86
|
+
const location = page.dir
|
|
87
|
+
? `${utils_1.SRC_PATH}/pages/${page.dir}/${page.title}`
|
|
88
|
+
: `${utils_1.SRC_PATH}/pages/${page.title}`;
|
|
89
|
+
if (page.dir) {
|
|
90
|
+
(0, utils_1.createDirectory)(`${utils_1.SRC_PATH}/pages/${page.dir}`);
|
|
91
|
+
}
|
|
92
|
+
return fs_1.default.promises.writeFile(location, page.content);
|
|
76
93
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
...creation(utils_2.utils, 'utils'),
|
|
89
|
-
...creation(components_1.components, 'components'),
|
|
90
|
-
...creation(styles_1.styles, 'styles'),
|
|
91
|
-
...creation(root_1.root),
|
|
92
|
-
...pageCreation,
|
|
93
|
-
]);
|
|
94
|
+
await Promise.all([
|
|
95
|
+
...creation(utils_2.utils, 'utils'),
|
|
96
|
+
...creation(components_1.components, 'components'),
|
|
97
|
+
...creation(styles_1.styles, 'styles'),
|
|
98
|
+
...creation(root_1.root),
|
|
99
|
+
...pageCreation,
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new Error('Error creating app files');
|
|
104
|
+
}
|
|
94
105
|
};
|
|
95
106
|
const generateEmailsPreview = async () => {
|
|
96
107
|
const spinner = (0, ora_1.default)('Generating emails preview').start();
|
|
@@ -139,7 +150,7 @@ const syncPkg = async () => {
|
|
|
139
150
|
const installDependencies = async () => {
|
|
140
151
|
const spinner = (0, ora_1.default)('Installing dependencies...').start();
|
|
141
152
|
shelljs_1.default.cd(path_1.default.join(utils_1.REACT_EMAIL_ROOT));
|
|
142
|
-
shelljs_1.default.exec('yarn'
|
|
153
|
+
shelljs_1.default.exec('yarn');
|
|
143
154
|
spinner.stopAndPersist({
|
|
144
155
|
symbol: log_symbols_1.default.success,
|
|
145
156
|
text: 'Dependencies installed',
|
|
@@ -29,15 +29,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.exportTemplates = void 0;
|
|
30
30
|
const glob_1 = require("glob");
|
|
31
31
|
const esbuild_1 = __importDefault(require("esbuild"));
|
|
32
|
+
const tree_node_cli_1 = __importDefault(require("tree-node-cli"));
|
|
33
|
+
const ora_1 = __importDefault(require("ora"));
|
|
34
|
+
const log_symbols_1 = __importDefault(require("log-symbols"));
|
|
32
35
|
const render_1 = require("@react-email/render");
|
|
33
36
|
const fs_1 = require("fs");
|
|
37
|
+
const cpy_1 = __importDefault(require("cpy"));
|
|
38
|
+
const utils_1 = require("../utils");
|
|
34
39
|
/*
|
|
35
40
|
This first builds all the templates using esbuild and then puts the output in the `.js`
|
|
36
41
|
files. Then these `.js` files are imported dynamically and rendered to `.html` files
|
|
37
42
|
using the `render` function.
|
|
38
43
|
*/
|
|
39
44
|
const exportTemplates = async (outDir, pretty) => {
|
|
40
|
-
const
|
|
45
|
+
const spinner = (0, ora_1.default)('Preparing files...\n').start();
|
|
46
|
+
const allTemplates = glob_1.glob.sync(`${utils_1.CLIENT_EMAILS_PATH}/*.{tsx,jsx}`);
|
|
41
47
|
esbuild_1.default.buildSync({
|
|
42
48
|
bundle: true,
|
|
43
49
|
entryPoints: allTemplates,
|
|
@@ -55,5 +61,18 @@ const exportTemplates = async (outDir, pretty) => {
|
|
|
55
61
|
(0, fs_1.writeFileSync)(htmlPath, rendered);
|
|
56
62
|
(0, fs_1.unlinkSync)(template);
|
|
57
63
|
}
|
|
64
|
+
const hasStaticDirectory = (0, utils_1.checkDirectoryExist)(`${utils_1.CLIENT_EMAILS_PATH}/static`);
|
|
65
|
+
if (hasStaticDirectory) {
|
|
66
|
+
await (0, cpy_1.default)(`${utils_1.CLIENT_EMAILS_PATH}/static`, `${outDir}/static`);
|
|
67
|
+
}
|
|
68
|
+
const fileTree = (0, tree_node_cli_1.default)(outDir, {
|
|
69
|
+
allFiles: true,
|
|
70
|
+
maxDepth: 4,
|
|
71
|
+
});
|
|
72
|
+
console.log(fileTree);
|
|
73
|
+
spinner.stopAndPersist({
|
|
74
|
+
symbol: log_symbols_1.default.success,
|
|
75
|
+
text: 'Successfully exported emails',
|
|
76
|
+
});
|
|
58
77
|
};
|
|
59
78
|
exports.exportTemplates = exportTemplates;
|
package/dist/utils/watcher.d.ts
CHANGED
package/dist/utils/watcher.js
CHANGED
|
@@ -3,15 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.watcher = void 0;
|
|
6
|
+
exports.watcher = exports.watcherInstance = void 0;
|
|
7
7
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
8
8
|
const constants_1 = require("./constants");
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const cpy_1 = __importDefault(require("cpy"));
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
12
|
+
exports.watcherInstance = chokidar_1.default.watch(constants_1.CLIENT_EMAILS_PATH, {
|
|
13
|
+
ignoreInitial: true,
|
|
14
|
+
cwd: constants_1.CURRENT_PATH,
|
|
15
|
+
ignored: /(^|[\/\\])\../,
|
|
16
|
+
});
|
|
17
|
+
const watcher = () => exports.watcherInstance.on('all', async (event, filename) => {
|
|
15
18
|
if (event === constants_1.EVENT_FILE_DELETED) {
|
|
16
19
|
const file = filename.split('/');
|
|
17
20
|
if (file[1] === 'static') {
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Button } from '@react-email/button';
|
|
2
|
+
import { Container } from '@react-email/container';
|
|
3
|
+
import { Head } from '@react-email/head';
|
|
4
|
+
import { Hr } from '@react-email/hr';
|
|
5
|
+
import { Html } from '@react-email/html';
|
|
6
|
+
import { Img } from '@react-email/img';
|
|
7
|
+
import { Link } from '@react-email/link';
|
|
8
|
+
import { Preview } from '@react-email/preview';
|
|
9
|
+
import { Section } from '@react-email/section';
|
|
10
|
+
import { Text } from '@react-email/text';
|
|
11
|
+
import * as React from 'react';
|
|
12
|
+
|
|
13
|
+
export default function Email() {
|
|
14
|
+
return (
|
|
15
|
+
<Html>
|
|
16
|
+
<Head />
|
|
17
|
+
<Preview>Read Alex's review</Preview>
|
|
18
|
+
<Section style={main}>
|
|
19
|
+
<Container style={container}>
|
|
20
|
+
<Img
|
|
21
|
+
src="/static/airbnb-logo.png"
|
|
22
|
+
width="96"
|
|
23
|
+
height="30"
|
|
24
|
+
alt="Airbnb"
|
|
25
|
+
/>
|
|
26
|
+
<Section>
|
|
27
|
+
<Img
|
|
28
|
+
src="/static/airbnb-review-user.jpg"
|
|
29
|
+
width="96"
|
|
30
|
+
height="96"
|
|
31
|
+
alt="Alex"
|
|
32
|
+
style={userImage}
|
|
33
|
+
/>
|
|
34
|
+
</Section>
|
|
35
|
+
<Text style={heading}>Here's what Alex wrote</Text>
|
|
36
|
+
<Text style={review}>
|
|
37
|
+
“Zeno was a great guest! Easy communication, the apartment was left
|
|
38
|
+
in great condition, very polite, and respectful of all house rules.
|
|
39
|
+
He’s welcome back anytime and would easily recommend him to any
|
|
40
|
+
host!”
|
|
41
|
+
</Text>
|
|
42
|
+
<Text style={paragraph}>
|
|
43
|
+
Now that the review period is over, we’ve posted Alex’s review to
|
|
44
|
+
your Airbnb profile.
|
|
45
|
+
</Text>
|
|
46
|
+
<Text style={paragraph}>
|
|
47
|
+
While it’s too late to write a review of your own, you can send your
|
|
48
|
+
feedback to Alex using your Airbnb message thread.
|
|
49
|
+
</Text>
|
|
50
|
+
<Section style={{ padding: '16px 0 20px' }}>
|
|
51
|
+
<Button pY={19} style={button} href="https://airbnb.com/">
|
|
52
|
+
Send My Feedback
|
|
53
|
+
</Button>
|
|
54
|
+
</Section>
|
|
55
|
+
<Hr style={hr} />
|
|
56
|
+
<Text style={{ ...paragraph, fontWeight: '700' }}>
|
|
57
|
+
Commom questions
|
|
58
|
+
</Text>
|
|
59
|
+
<Text>
|
|
60
|
+
<Link href="https://airbnb.com/help/article/13" style={link}>
|
|
61
|
+
How do reviews work?
|
|
62
|
+
</Link>
|
|
63
|
+
</Text>
|
|
64
|
+
<Text>
|
|
65
|
+
<Link href="https://airbnb.com/help/article/1257" style={link}>
|
|
66
|
+
How do star ratings work?
|
|
67
|
+
</Link>
|
|
68
|
+
</Text>
|
|
69
|
+
<Text>
|
|
70
|
+
<Link href="https://airbnb.com/help/article/995" style={link}>
|
|
71
|
+
Can I leave a review after 14 days?
|
|
72
|
+
</Link>
|
|
73
|
+
</Text>
|
|
74
|
+
<Hr style={hr} />
|
|
75
|
+
<Text style={footer}>
|
|
76
|
+
Airbnb, Inc., 888 Brannan St, San Francisco, CA 94103
|
|
77
|
+
</Text>
|
|
78
|
+
<Link href="https://airbnb.com" style={reportLink}>
|
|
79
|
+
Report unsafe behavior
|
|
80
|
+
</Link>
|
|
81
|
+
</Container>
|
|
82
|
+
</Section>
|
|
83
|
+
</Html>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const fontFamily =
|
|
88
|
+
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif';
|
|
89
|
+
|
|
90
|
+
const main = {
|
|
91
|
+
backgroundColor: '#ffffff',
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const container = {
|
|
95
|
+
margin: '0 auto',
|
|
96
|
+
padding: '20px 0 48px',
|
|
97
|
+
width: '580px',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const userImage = {
|
|
101
|
+
margin: '0 auto',
|
|
102
|
+
marginBottom: '16px',
|
|
103
|
+
borderRadius: '50%',
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const heading = {
|
|
107
|
+
fontFamily,
|
|
108
|
+
fontSize: '32px',
|
|
109
|
+
lineHeight: '1.3',
|
|
110
|
+
fontWeight: '700',
|
|
111
|
+
color: '#484848',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const paragraph = {
|
|
115
|
+
fontFamily,
|
|
116
|
+
fontSize: '18px',
|
|
117
|
+
lineHeight: '1.4',
|
|
118
|
+
color: '#484848',
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const review = {
|
|
122
|
+
...paragraph,
|
|
123
|
+
padding: '24px',
|
|
124
|
+
backgroundColor: '#f2f3f3',
|
|
125
|
+
borderRadius: '4px',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const button = {
|
|
129
|
+
fontFamily,
|
|
130
|
+
backgroundColor: '#ff5a5f',
|
|
131
|
+
borderRadius: '3px',
|
|
132
|
+
color: '#fff',
|
|
133
|
+
fontSize: '18px',
|
|
134
|
+
textDecoration: 'none',
|
|
135
|
+
textAlign: 'center' as const,
|
|
136
|
+
display: 'block',
|
|
137
|
+
width: '100%',
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const link = {
|
|
141
|
+
...paragraph,
|
|
142
|
+
color: '#ff5a5f',
|
|
143
|
+
display: 'block',
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const reportLink = {
|
|
147
|
+
fontFamily,
|
|
148
|
+
fontSize: '14px',
|
|
149
|
+
color: '#9ca299',
|
|
150
|
+
textDecoration: 'underline',
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const hr = {
|
|
154
|
+
borderColor: '#cccccc',
|
|
155
|
+
margin: '20px 0',
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const footer = {
|
|
159
|
+
fontFamily,
|
|
160
|
+
color: '#9ca299',
|
|
161
|
+
fontSize: '14px',
|
|
162
|
+
marginBottom: '10px',
|
|
163
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Button } from '@react-email/button';
|
|
2
|
+
import { Container } from '@react-email/container';
|
|
3
|
+
import { Head } from '@react-email/head';
|
|
4
|
+
import { Html } from '@react-email/html';
|
|
5
|
+
import { Img } from '@react-email/img';
|
|
6
|
+
import { Link } from '@react-email/link';
|
|
7
|
+
import { Preview } from '@react-email/preview';
|
|
8
|
+
import { Section } from '@react-email/section';
|
|
9
|
+
import { Text } from '@react-email/text';
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
|
|
12
|
+
export default function Email() {
|
|
13
|
+
return (
|
|
14
|
+
<Html>
|
|
15
|
+
<Head />
|
|
16
|
+
<Preview>Dropbox reset your password</Preview>
|
|
17
|
+
<Section style={main}>
|
|
18
|
+
<Container style={container}>
|
|
19
|
+
<Img src="/static/dropbox.png" width="40" height="33" alt="Dropbox" />
|
|
20
|
+
<Section>
|
|
21
|
+
<Text style={text}>Hi Zeno,</Text>
|
|
22
|
+
<Text style={text}>
|
|
23
|
+
Someone recently requested a password change for your Dropbox
|
|
24
|
+
account. If this was you, you can set a new password here:
|
|
25
|
+
</Text>
|
|
26
|
+
<Button style={button} href="https://dropbox.com">
|
|
27
|
+
Reset password
|
|
28
|
+
</Button>
|
|
29
|
+
<Text style={text}>
|
|
30
|
+
If you don't want to change your password or didn't
|
|
31
|
+
request this, just ignore and delete this message.
|
|
32
|
+
</Text>
|
|
33
|
+
<Text style={text}>
|
|
34
|
+
To keep your account secure, please don't forward this email
|
|
35
|
+
to anyone. See our Help Center for{' '}
|
|
36
|
+
<Link style={anchor} href="https://dropbox.com">
|
|
37
|
+
more security tips.
|
|
38
|
+
</Link>
|
|
39
|
+
</Text>
|
|
40
|
+
<Text style={text}>Happy Dropboxing!</Text>
|
|
41
|
+
</Section>
|
|
42
|
+
</Container>
|
|
43
|
+
</Section>
|
|
44
|
+
</Html>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const main = {
|
|
49
|
+
backgroundColor: '#f6f9fc',
|
|
50
|
+
padding: '10px 0',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const container = {
|
|
54
|
+
margin: '0 auto',
|
|
55
|
+
backgroundColor: '#ffffff',
|
|
56
|
+
border: '1px solid #f0f0f0',
|
|
57
|
+
width: '600px',
|
|
58
|
+
padding: '45px',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const text = {
|
|
62
|
+
fontSize: '16px',
|
|
63
|
+
fontFamily:
|
|
64
|
+
"'Open Sans', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif",
|
|
65
|
+
fontWeight: '300',
|
|
66
|
+
color: '#404040',
|
|
67
|
+
lineHeight: '26px',
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const button = {
|
|
71
|
+
backgroundColor: '#007ee6',
|
|
72
|
+
borderRadius: '4px',
|
|
73
|
+
color: '#fff',
|
|
74
|
+
fontFamily: "'Open Sans', 'Helvetica Neue', Arial",
|
|
75
|
+
fontSize: '15px',
|
|
76
|
+
textDecoration: 'none',
|
|
77
|
+
textAlign: 'center' as const,
|
|
78
|
+
display: 'block',
|
|
79
|
+
width: '210px',
|
|
80
|
+
padding: '14px 7px',
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const anchor = {
|
|
84
|
+
textDecoration: 'underline',
|
|
85
|
+
};
|