@react-email/preview-server 4.1.0-canary.9 → 4.1.1
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/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +32 -32
- package/.next/build-manifest.json +14 -14
- package/.next/diagnostics/framework.json +1 -1
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page.js +1 -1
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/favicon.ico/route.js +1 -1
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/page.js +1 -1
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/preview/[...slug]/page.js +356 -174
- package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -1
- package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -1
- package/.next/server/chunks/161.js +1 -0
- package/.next/server/chunks/277.js +1 -0
- package/.next/server/chunks/{879.js → 532.js} +7 -7
- package/.next/server/chunks/550.js +6 -0
- package/.next/server/chunks/834.js +15 -0
- package/.next/server/chunks/851.js +20 -0
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages/_app.js +1 -1
- package/.next/server/pages/_app.js.nft.json +1 -1
- package/.next/server/pages/_document.js +1 -1
- package/.next/server/pages/_document.js.nft.json +1 -1
- package/.next/server/pages/_error.js +1 -1
- package/.next/server/pages/_error.js.nft.json +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/{pT9c18D6E8gNsHAfpxTUA → 9kTcwkEeDkXsMQ7fDAu2v}/_buildManifest.js +1 -1
- package/.next/static/chunks/343-0aa226f42148dce4.js +1 -0
- package/.next/static/chunks/353-5e7d05b120b2e25f.js +1 -0
- package/.next/static/chunks/445-576b0c51a037fe4d.js +1 -0
- package/.next/static/chunks/483-fd8ad4ef179f4f6e.js +1 -0
- package/.next/static/chunks/624-9d1650c8211771cd.js +1 -0
- package/.next/static/chunks/755-01456539a6894956.js +1 -0
- package/.next/static/chunks/app/_not-found/{page-aee2c5619f94a965.js → page-e9c9ee8e737ce3f8.js} +1 -1
- package/.next/static/chunks/app/layout-8dda0c80b5cdbeb7.js +1 -0
- package/.next/static/chunks/app/page-ee81303e36f65d71.js +1 -0
- package/.next/static/chunks/app/preview/[...slug]/page-e54371fcb72010fe.js +1 -0
- package/.next/static/chunks/{04c799b8-f2be86d6e75dbf29.js → e8809b48-6a73b3f51ba71e9c.js} +1 -1
- package/.next/static/chunks/{f33a14d2-188715a58266ac15.js → f33a14d2-13f6de3d216cf617.js} +1 -1
- package/.next/static/chunks/framework-4f208795521d076c.js +1 -0
- package/.next/static/chunks/main-0000d0a5ac74fec0.js +1 -0
- package/.next/static/chunks/main-app-5ba7fd8e7a976edb.js +1 -0
- package/.next/static/chunks/pages/_app-550e3587fddcaa19.js +1 -0
- package/.next/static/chunks/pages/_error-870af0ad63b0e49e.js +1 -0
- package/.next/static/chunks/{webpack-c09dcf4c47767be8.js → webpack-fc6f324c4c88f6e3.js} +1 -1
- package/.next/static/css/48dcea18d820a298.css +3 -0
- package/.next/trace +27 -27
- package/CHANGELOG.md +29 -0
- package/package.json +6 -4
- package/readme.md +35 -0
- package/scripts/dev.mts +47 -0
- package/scripts/{fill-caniemail-data.mjs → fill-caniemail-data.mts} +0 -5
- package/scripts/seed.mts +21 -0
- package/scripts/utils/default-seed/auth/account-confirmation.tsx +68 -0
- package/scripts/utils/default-seed/auth/forgot-password.tsx +71 -0
- package/scripts/utils/default-seed/communications/payment-overdue.tsx +82 -0
- package/scripts/utils/default-seed/communications/team-invite.tsx +78 -0
- package/scripts/utils/default-seed/communications/webhooks-failed.tsx +89 -0
- package/scripts/utils/default-seed/feedback-request.tsx +78 -0
- package/scripts/utils/default-seed/marketing/changelog.tsx +98 -0
- package/src/actions/email-validation/__snapshots__/check-images.spec.tsx.snap +84 -0
- package/src/actions/email-validation/check-images.spec.tsx +1 -80
- package/src/app/layout.tsx +2 -2
- package/src/app/preview/[...slug]/preview.tsx +1 -1
- package/src/components/code-container.tsx +3 -1
- package/src/components/code.tsx +60 -59
- package/src/components/logo.tsx +68 -63
- package/src/components/send.tsx +8 -5
- package/src/components/shell.tsx +4 -1
- package/src/components/sidebar/file-tree-directory-children.tsx +4 -1
- package/src/components/toolbar.tsx +9 -5
- package/src/contexts/emails.tsx +2 -2
- package/src/contexts/preview.tsx +2 -2
- package/src/hooks/use-email-rendering-result.ts +2 -2
- package/src/utils/__snapshots__/get-email-component.spec.ts.snap +183 -1
- package/src/utils/caniemail/ast/get-used-style-properties.ts +1 -0
- package/src/utils/contains-email-template.spec.ts +12 -0
- package/src/utils/contains-email-template.ts +26 -9
- package/src/utils/get-email-component.spec.ts +3 -0
- package/.next/server/chunks/200.js +0 -1
- package/.next/server/chunks/3.js +0 -15
- package/.next/server/chunks/784.js +0 -6
- package/.next/server/chunks/823.js +0 -1
- package/.next/server/chunks/915.js +0 -20
- package/.next/static/chunks/188-e278e5f1e9c4067e.js +0 -1
- package/.next/static/chunks/336-0767fdc0ff1ceaa1.js +0 -1
- package/.next/static/chunks/551-d9ce0a77591e6bf7.js +0 -1
- package/.next/static/chunks/651-337b0388fdb8c85c.js +0 -1
- package/.next/static/chunks/713-6c7607cb54b8278e.js +0 -1
- package/.next/static/chunks/834-e77d5196a2631efe.js +0 -1
- package/.next/static/chunks/app/layout-4403d8068fbec772.js +0 -1
- package/.next/static/chunks/app/page-ddc5b5b5b8d2de0e.js +0 -1
- package/.next/static/chunks/app/preview/[...slug]/page-873416b81678fe6b.js +0 -1
- package/.next/static/chunks/framework-f71c687711cb40cc.js +0 -1
- package/.next/static/chunks/main-697e2f65b52ad05c.js +0 -1
- package/.next/static/chunks/main-app-deb9839bdc2bcbd4.js +0 -1
- package/.next/static/chunks/pages/_app-2e335329c12ac3e7.js +0 -1
- package/.next/static/chunks/pages/_error-73094c2ebe868f44.js +0 -1
- package/.next/static/css/692fd92effde156a.css +0 -3
- /package/.next/static/{pT9c18D6E8gNsHAfpxTUA → 9kTcwkEeDkXsMQ7fDAu2v}/_ssgManifest.js +0 -0
- /package/scripts/{build-preview-server.mjs → build-preview-server.mts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @react-email/preview-server
|
|
2
2
|
|
|
3
|
+
## 4.1.1
|
|
4
|
+
|
|
5
|
+
## 4.1.0
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- e173b44: Use the same version for the preview-server and react-email
|
|
10
|
+
- e33be94: fix range rounded borders, tearing when selecting different lines
|
|
11
|
+
- 87b9601: infinte fetches due to improper effect dependency
|
|
12
|
+
|
|
13
|
+
## 4.1.0-canary.12
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- e33be94: fix range rounded borders, tearing when selecting different lines
|
|
18
|
+
- 87b9601: infinte fetches due to improper effect dependency
|
|
19
|
+
|
|
20
|
+
## 4.1.0-canary.11
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- 272b21e: fix the forced `color-scheme: dark` for the preview
|
|
25
|
+
|
|
26
|
+
## 4.1.0-canary.10
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- caa4a31: fix hot reloading with collapsed directories
|
|
31
|
+
|
|
3
32
|
## 4.1.0-canary.9
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-email/preview-server",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "A live preview of your emails right in your browser.",
|
|
5
5
|
"main": "./index.mjs",
|
|
6
6
|
"dependencies": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"postcss": "8.5.3",
|
|
62
62
|
"tailwindcss": "3.4.0",
|
|
63
63
|
"typescript": "5.8.3",
|
|
64
|
-
"@react-email/components": "0.
|
|
64
|
+
"@react-email/components": "0.2.0"
|
|
65
65
|
},
|
|
66
66
|
"license": "MIT",
|
|
67
67
|
"repository": {
|
|
@@ -73,9 +73,11 @@
|
|
|
73
73
|
"access": "public"
|
|
74
74
|
},
|
|
75
75
|
"scripts": {
|
|
76
|
-
"
|
|
76
|
+
"build": "tsx ./scripts/build-preview-server.mts",
|
|
77
|
+
"caniemail:fetch": "tsx ./scripts/fill-caniemail-data.mts",
|
|
77
78
|
"clean": "rm -rf dist",
|
|
78
|
-
"
|
|
79
|
+
"dev": "tsx ./scripts/dev.mts",
|
|
80
|
+
"dev:seed": "tsx ./scripts/seed.mts",
|
|
79
81
|
"test": "vitest run",
|
|
80
82
|
"test:watch": "vitest"
|
|
81
83
|
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<div align="center"><strong>@react-email/preview-server</strong></div>
|
|
2
|
+
<div align="center">A live preview of your emails right in your browser.</div>
|
|
3
|
+
<br />
|
|
4
|
+
<div align="center">
|
|
5
|
+
<a href="https://react.email">Website</a>
|
|
6
|
+
<span> · </span>
|
|
7
|
+
<a href="https://github.com/resend/react-email">GitHub</a>
|
|
8
|
+
<span> · </span>
|
|
9
|
+
<a href="https://react.email/discord">Discord</a>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
This package is used to store the preview server, it is also published and versioned so that it can be installed when the [CLI](../react-email) is being used.
|
|
13
|
+
|
|
14
|
+
## Development workflow
|
|
15
|
+
|
|
16
|
+
### 1. Seed email templates
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pnpm dev:seed
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This generates a boilerplate emails directory for you to work with. These files can also be modified as you see fit since they are not included in git.
|
|
23
|
+
|
|
24
|
+
### 2. Run development server
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm dev
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This is somewhat equivalent to `next dev` and does not support hot reloading for email templates like the CLI does. It lets you work on the UI for the preview server mainly.
|
|
31
|
+
|
|
32
|
+
### 3. Open in your browser
|
|
33
|
+
|
|
34
|
+
Go to http://localhost:3000
|
|
35
|
+
|
package/scripts/dev.mts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import child_process from 'node:child_process';
|
|
2
|
+
import { promises as fs } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import url from 'node:url';
|
|
5
|
+
|
|
6
|
+
const filename = url.fileURLToPath(import.meta.url);
|
|
7
|
+
const dirname = path.dirname(filename);
|
|
8
|
+
|
|
9
|
+
const previewServerRoot = path.resolve(dirname, '..');
|
|
10
|
+
const emailsDirectoryPath = path.join(previewServerRoot, 'emails');
|
|
11
|
+
|
|
12
|
+
const envPath = path.join(previewServerRoot, '.env.local');
|
|
13
|
+
|
|
14
|
+
await fs.writeFile(
|
|
15
|
+
envPath,
|
|
16
|
+
`EMAILS_DIR_RELATIVE_PATH=./emails
|
|
17
|
+
EMAILS_DIR_ABSOLUTE_PATH=${emailsDirectoryPath}
|
|
18
|
+
USER_PROJECT_LOCATION=${previewServerRoot}
|
|
19
|
+
NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT=true`,
|
|
20
|
+
'utf8',
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const webServerProcess = child_process.spawn('next', ['dev'], {
|
|
24
|
+
cwd: previewServerRoot,
|
|
25
|
+
shell: true,
|
|
26
|
+
stdio: 'inherit',
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
webServerProcess.on('exit', async () => {
|
|
30
|
+
await fs.rm(envPath);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
process.on('SIGINT', () => {
|
|
34
|
+
webServerProcess.kill('SIGINT');
|
|
35
|
+
});
|
|
36
|
+
process.on('SIGUSR1', () => {
|
|
37
|
+
webServerProcess.kill('SIGUSR1');
|
|
38
|
+
});
|
|
39
|
+
process.on('SIGUSR2', () => {
|
|
40
|
+
webServerProcess.kill('SIGUSR2');
|
|
41
|
+
});
|
|
42
|
+
process.on('uncaughtExceptionMonitor', () => {
|
|
43
|
+
webServerProcess.kill();
|
|
44
|
+
});
|
|
45
|
+
process.on('exit', () => {
|
|
46
|
+
webServerProcess.kill();
|
|
47
|
+
});
|
|
@@ -14,11 +14,6 @@ This could be happneing for the following reasons:
|
|
|
14
14
|
- You don't have internet connectivity
|
|
15
15
|
- Caniemail is down
|
|
16
16
|
- Caniemail changed from where to fetch their data from, which means we need to fix this. If this is the case, please open up an issue.`,
|
|
17
|
-
{
|
|
18
|
-
cause: {
|
|
19
|
-
responseFromCaniemail,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
17
|
);
|
|
23
18
|
}
|
|
24
19
|
|
package/scripts/seed.mts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { existsSync, promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import url from 'node:url';
|
|
4
|
+
|
|
5
|
+
const filename = url.fileURLToPath(import.meta.url);
|
|
6
|
+
const dirname = path.dirname(filename);
|
|
7
|
+
|
|
8
|
+
const previewServerRoot = path.resolve(dirname, '..');
|
|
9
|
+
const emailsDirectoryPath = path.join(previewServerRoot, 'emails');
|
|
10
|
+
|
|
11
|
+
const seedPath = path.join(dirname, './utils/default-seed/');
|
|
12
|
+
|
|
13
|
+
if (existsSync(emailsDirectoryPath)) {
|
|
14
|
+
console.info('Deleting previous emails directory');
|
|
15
|
+
await fs.rm(emailsDirectoryPath, { recursive: true, force: true });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.info('Copying over the defalt seed to the emails directory');
|
|
19
|
+
await fs.cp(seedPath, emailsDirectoryPath, {
|
|
20
|
+
recursive: true,
|
|
21
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Column,
|
|
5
|
+
Container,
|
|
6
|
+
Head,
|
|
7
|
+
Heading,
|
|
8
|
+
Hr,
|
|
9
|
+
Html,
|
|
10
|
+
Preview,
|
|
11
|
+
Row,
|
|
12
|
+
Tailwind,
|
|
13
|
+
Text,
|
|
14
|
+
} from '@react-email/components';
|
|
15
|
+
|
|
16
|
+
interface AccountConfirmationProps {
|
|
17
|
+
confirmLink: string;
|
|
18
|
+
expiryTime: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default function AccountConfirmation({
|
|
22
|
+
confirmLink,
|
|
23
|
+
expiryTime,
|
|
24
|
+
}: AccountConfirmationProps) {
|
|
25
|
+
return (
|
|
26
|
+
<Html>
|
|
27
|
+
<Head />
|
|
28
|
+
<Tailwind>
|
|
29
|
+
<Body className="bg-black text-white">
|
|
30
|
+
<Preview>Confirm your React Email account</Preview>
|
|
31
|
+
<Container className="mx-auto">
|
|
32
|
+
<Heading className="font-bold text-center my-[48px] text-[32px]">
|
|
33
|
+
Welcome to React Email!
|
|
34
|
+
</Heading>
|
|
35
|
+
<Text>
|
|
36
|
+
Thank you for signing up! To complete your registration and start
|
|
37
|
+
using React Email, please confirm your email address.
|
|
38
|
+
</Text>
|
|
39
|
+
<Text className="mb-6">
|
|
40
|
+
Click the button below to verify your email. This link will expire
|
|
41
|
+
in {expiryTime}.
|
|
42
|
+
</Text>
|
|
43
|
+
<Row className="w-full">
|
|
44
|
+
<Column className="w-full">
|
|
45
|
+
<Button
|
|
46
|
+
href={confirmLink}
|
|
47
|
+
className="bg-cyan-300 text-[20px] font-bold text-[#404040] w-full text-center border border-solid border-cyan-900 py-[8px] rounded-[8px]"
|
|
48
|
+
>
|
|
49
|
+
Confirm Email
|
|
50
|
+
</Button>
|
|
51
|
+
</Column>
|
|
52
|
+
</Row>
|
|
53
|
+
<Text className="mt-6">- React Email team</Text>
|
|
54
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
55
|
+
<Text className="text-[#606060] font-bold">
|
|
56
|
+
React Email, 999 React St, Email City, EC 12345
|
|
57
|
+
</Text>
|
|
58
|
+
</Container>
|
|
59
|
+
</Body>
|
|
60
|
+
</Tailwind>
|
|
61
|
+
</Html>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
AccountConfirmation.PreviewProps = {
|
|
66
|
+
confirmLink: 'https://react.email/confirm/123',
|
|
67
|
+
expiryTime: '24 hours',
|
|
68
|
+
} satisfies AccountConfirmationProps;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Column,
|
|
5
|
+
Container,
|
|
6
|
+
Head,
|
|
7
|
+
Heading,
|
|
8
|
+
Hr,
|
|
9
|
+
Html,
|
|
10
|
+
Preview,
|
|
11
|
+
Row,
|
|
12
|
+
Tailwind,
|
|
13
|
+
Text,
|
|
14
|
+
} from '@react-email/components';
|
|
15
|
+
|
|
16
|
+
interface ForgotPasswordProps {
|
|
17
|
+
resetLink: string;
|
|
18
|
+
expiryTime: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default function ForgotPassword({
|
|
22
|
+
resetLink,
|
|
23
|
+
expiryTime,
|
|
24
|
+
}: ForgotPasswordProps) {
|
|
25
|
+
return (
|
|
26
|
+
<Html>
|
|
27
|
+
<Head />
|
|
28
|
+
<Tailwind>
|
|
29
|
+
<Body className="bg-black text-white">
|
|
30
|
+
<Preview>Reset your React Email password</Preview>
|
|
31
|
+
<Container className="mx-auto">
|
|
32
|
+
<Heading className="font-bold text-center my-[48px] text-[32px]">
|
|
33
|
+
Reset Your Password
|
|
34
|
+
</Heading>
|
|
35
|
+
<Text>
|
|
36
|
+
We received a request to reset your password for your React Email
|
|
37
|
+
account.
|
|
38
|
+
</Text>
|
|
39
|
+
<Text>
|
|
40
|
+
Click the button below to create a new password. This link will
|
|
41
|
+
expire in {expiryTime}.
|
|
42
|
+
</Text>
|
|
43
|
+
<Text className="mb-6">
|
|
44
|
+
If you didn't request this, you can safely ignore this email.
|
|
45
|
+
</Text>
|
|
46
|
+
<Row className="w-full">
|
|
47
|
+
<Column className="w-full">
|
|
48
|
+
<Button
|
|
49
|
+
href={resetLink}
|
|
50
|
+
className="bg-cyan-300 text-[20px] font-bold text-[#404040] w-full text-center border border-solid border-cyan-900 py-[8px] rounded-[8px]"
|
|
51
|
+
>
|
|
52
|
+
Reset Password
|
|
53
|
+
</Button>
|
|
54
|
+
</Column>
|
|
55
|
+
</Row>
|
|
56
|
+
<Text className="mt-6">- React Email team</Text>
|
|
57
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
58
|
+
<Text className="text-[#606060] font-bold">
|
|
59
|
+
React Email, 999 React St, Email City, EC 12345
|
|
60
|
+
</Text>
|
|
61
|
+
</Container>
|
|
62
|
+
</Body>
|
|
63
|
+
</Tailwind>
|
|
64
|
+
</Html>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
ForgotPassword.PreviewProps = {
|
|
69
|
+
resetLink: 'https://react.email/reset-password/123',
|
|
70
|
+
expiryTime: '1 hour',
|
|
71
|
+
} satisfies ForgotPasswordProps;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Column,
|
|
5
|
+
Container,
|
|
6
|
+
Head,
|
|
7
|
+
Heading,
|
|
8
|
+
Hr,
|
|
9
|
+
Html,
|
|
10
|
+
Preview,
|
|
11
|
+
Row,
|
|
12
|
+
Tailwind,
|
|
13
|
+
Text,
|
|
14
|
+
} from '@react-email/components';
|
|
15
|
+
|
|
16
|
+
interface PaymentOverdueProps {
|
|
17
|
+
customerName: string;
|
|
18
|
+
amount: string;
|
|
19
|
+
dueDate: string;
|
|
20
|
+
invoiceLink: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function PaymentOverdue({
|
|
24
|
+
customerName,
|
|
25
|
+
amount,
|
|
26
|
+
dueDate,
|
|
27
|
+
invoiceLink,
|
|
28
|
+
}: PaymentOverdueProps) {
|
|
29
|
+
return (
|
|
30
|
+
<Html>
|
|
31
|
+
<Head />
|
|
32
|
+
<Tailwind>
|
|
33
|
+
<Body className="bg-black text-white">
|
|
34
|
+
<Preview>Payment of {amount} is overdue - Action required</Preview>
|
|
35
|
+
<Container className="mx-auto">
|
|
36
|
+
<Heading className="font-bold text-center my-[48px] text-[32px]">
|
|
37
|
+
Payment Overdue
|
|
38
|
+
</Heading>
|
|
39
|
+
<Text>Dear {customerName},</Text>
|
|
40
|
+
<Text>
|
|
41
|
+
We noticed that your payment of {amount} was due on {dueDate} and
|
|
42
|
+
has not been received yet.
|
|
43
|
+
</Text>
|
|
44
|
+
<Text>
|
|
45
|
+
To avoid any service interruption, please process your payment as
|
|
46
|
+
soon as possible.
|
|
47
|
+
</Text>
|
|
48
|
+
<Text className="mb-6">
|
|
49
|
+
You can view and pay your invoice by clicking the button below:
|
|
50
|
+
</Text>
|
|
51
|
+
<Row className="w-full">
|
|
52
|
+
<Column className="w-full">
|
|
53
|
+
<Button
|
|
54
|
+
href={invoiceLink}
|
|
55
|
+
className="bg-cyan-300 text-[20px] font-bold text-[#404040] w-full text-center border border-solid border-cyan-900 py-[8px] rounded-[8px]"
|
|
56
|
+
>
|
|
57
|
+
Pay Now
|
|
58
|
+
</Button>
|
|
59
|
+
</Column>
|
|
60
|
+
</Row>
|
|
61
|
+
<Text className="mt-6">
|
|
62
|
+
If you have already made this payment, please disregard this
|
|
63
|
+
message.
|
|
64
|
+
</Text>
|
|
65
|
+
<Text className="mt-6">- React Email team</Text>
|
|
66
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
67
|
+
<Text className="text-[#606060] font-bold">
|
|
68
|
+
React Email, 999 React St, Email City, EC 12345
|
|
69
|
+
</Text>
|
|
70
|
+
</Container>
|
|
71
|
+
</Body>
|
|
72
|
+
</Tailwind>
|
|
73
|
+
</Html>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
PaymentOverdue.PreviewProps = {
|
|
78
|
+
customerName: 'Jane Smith',
|
|
79
|
+
amount: '$99.00',
|
|
80
|
+
dueDate: 'June 1st, 2024',
|
|
81
|
+
invoiceLink: 'https://react.email/invoice/123',
|
|
82
|
+
} satisfies PaymentOverdueProps;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Column,
|
|
5
|
+
Container,
|
|
6
|
+
Head,
|
|
7
|
+
Heading,
|
|
8
|
+
Hr,
|
|
9
|
+
Html,
|
|
10
|
+
Preview,
|
|
11
|
+
Row,
|
|
12
|
+
Tailwind,
|
|
13
|
+
Text,
|
|
14
|
+
} from '@react-email/components';
|
|
15
|
+
|
|
16
|
+
interface TeamInviteProps {
|
|
17
|
+
inviterName: string;
|
|
18
|
+
teamName: string;
|
|
19
|
+
inviteLink: string;
|
|
20
|
+
role: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default function TeamInvite({
|
|
24
|
+
inviterName,
|
|
25
|
+
teamName,
|
|
26
|
+
inviteLink,
|
|
27
|
+
role,
|
|
28
|
+
}: TeamInviteProps) {
|
|
29
|
+
return (
|
|
30
|
+
<Html>
|
|
31
|
+
<Head />
|
|
32
|
+
<Tailwind>
|
|
33
|
+
<Body className="bg-black text-white">
|
|
34
|
+
<Preview>
|
|
35
|
+
{inviterName} has invited you to join {teamName} on React Email
|
|
36
|
+
</Preview>
|
|
37
|
+
<Container className="mx-auto">
|
|
38
|
+
<Heading className="font-bold text-center my-[48px] text-[32px]">
|
|
39
|
+
You've been invited!
|
|
40
|
+
</Heading>
|
|
41
|
+
<Text>
|
|
42
|
+
{inviterName} has invited you to join {teamName} as a {role}.
|
|
43
|
+
</Text>
|
|
44
|
+
<Text>
|
|
45
|
+
React Email helps teams collaborate on email templates and manage
|
|
46
|
+
their email campaigns effectively.
|
|
47
|
+
</Text>
|
|
48
|
+
<Text className="mb-6">
|
|
49
|
+
Click the button below to accept the invitation and get started:
|
|
50
|
+
</Text>
|
|
51
|
+
<Row className="w-full">
|
|
52
|
+
<Column className="w-full">
|
|
53
|
+
<Button
|
|
54
|
+
href={inviteLink}
|
|
55
|
+
className="bg-cyan-300 text-[20px] font-bold text-[#404040] w-full text-center border border-solid border-cyan-900 py-[8px] rounded-[8px]"
|
|
56
|
+
>
|
|
57
|
+
Accept Invitation
|
|
58
|
+
</Button>
|
|
59
|
+
</Column>
|
|
60
|
+
</Row>
|
|
61
|
+
<Text className="mt-6">- React Email team</Text>
|
|
62
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
63
|
+
<Text className="text-[#606060] font-bold">
|
|
64
|
+
React Email, 999 React St, Email City, EC 12345
|
|
65
|
+
</Text>
|
|
66
|
+
</Container>
|
|
67
|
+
</Body>
|
|
68
|
+
</Tailwind>
|
|
69
|
+
</Html>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
TeamInvite.PreviewProps = {
|
|
74
|
+
inviterName: 'John Doe',
|
|
75
|
+
teamName: 'Marketing Team',
|
|
76
|
+
inviteLink: 'https://react.email/join/team/123',
|
|
77
|
+
role: 'Editor',
|
|
78
|
+
} satisfies TeamInviteProps;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
CodeBlock,
|
|
4
|
+
Container,
|
|
5
|
+
Head,
|
|
6
|
+
Heading,
|
|
7
|
+
Hr,
|
|
8
|
+
Html,
|
|
9
|
+
Preview,
|
|
10
|
+
Tailwind,
|
|
11
|
+
Text,
|
|
12
|
+
vesper,
|
|
13
|
+
} from '@react-email/components';
|
|
14
|
+
|
|
15
|
+
interface WebhooksFailedProps {
|
|
16
|
+
date: string;
|
|
17
|
+
error: {
|
|
18
|
+
error: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
webhookId: string;
|
|
21
|
+
details: {
|
|
22
|
+
reason: string;
|
|
23
|
+
retryCount: number;
|
|
24
|
+
lastAttempt: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default function WebhooksFailed({ date, error }: WebhooksFailedProps) {
|
|
30
|
+
return (
|
|
31
|
+
<Html>
|
|
32
|
+
<Head />
|
|
33
|
+
<Tailwind>
|
|
34
|
+
<Body className="bg-black text-white">
|
|
35
|
+
<Preview>Some webhooks failed to deliver at {date}</Preview>
|
|
36
|
+
<Container className="mx-auto">
|
|
37
|
+
<Heading className="font-bold text-center text-[32px]">
|
|
38
|
+
Failed webhook attempt
|
|
39
|
+
</Heading>
|
|
40
|
+
<Text>
|
|
41
|
+
We encountered an issue with some of our webhooks. Please check
|
|
42
|
+
the logs for more details. Here is the data for the error:
|
|
43
|
+
</Text>
|
|
44
|
+
<CodeBlock
|
|
45
|
+
code={JSON.stringify(error, null, 2)}
|
|
46
|
+
language="json"
|
|
47
|
+
theme={vesper}
|
|
48
|
+
style={{
|
|
49
|
+
padding: '16px',
|
|
50
|
+
borderRadius: '8px',
|
|
51
|
+
}}
|
|
52
|
+
lineNumbers
|
|
53
|
+
/>
|
|
54
|
+
<Text className="mb-6">
|
|
55
|
+
If you have any questions or need assistance, please reach out to
|
|
56
|
+
us at{' '}
|
|
57
|
+
<a
|
|
58
|
+
href="mailto:support@react.email"
|
|
59
|
+
className="text-cyan-300 underline"
|
|
60
|
+
>
|
|
61
|
+
support@react.email
|
|
62
|
+
</a>
|
|
63
|
+
.
|
|
64
|
+
</Text>
|
|
65
|
+
<Text className="mt-6">- React Email team</Text>
|
|
66
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
67
|
+
<Text className="text-[#606060] font-bold">
|
|
68
|
+
React Email, 999 React St, Email City, EC 12345
|
|
69
|
+
</Text>
|
|
70
|
+
</Container>
|
|
71
|
+
</Body>
|
|
72
|
+
</Tailwind>
|
|
73
|
+
</Html>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
WebhooksFailed.PreviewProps = {
|
|
78
|
+
date: 'June 4th, 202',
|
|
79
|
+
error: {
|
|
80
|
+
error: 'Webhook delivery failed',
|
|
81
|
+
timestamp: '2023-10-01T12:00:00Z',
|
|
82
|
+
webhookId: 'wh_1234567890',
|
|
83
|
+
details: {
|
|
84
|
+
reason: 'Network error',
|
|
85
|
+
retryCount: 3,
|
|
86
|
+
lastAttempt: '2023-10-01T12:05:00Z',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
} satisfies WebhooksFailedProps;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Column,
|
|
5
|
+
Container,
|
|
6
|
+
Head,
|
|
7
|
+
Heading,
|
|
8
|
+
Hr,
|
|
9
|
+
Html,
|
|
10
|
+
Preview,
|
|
11
|
+
Row,
|
|
12
|
+
Tailwind,
|
|
13
|
+
Text,
|
|
14
|
+
} from '@react-email/components';
|
|
15
|
+
|
|
16
|
+
interface FeedbackRequestProps {
|
|
17
|
+
name: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function FeedbackRequest({ name }: FeedbackRequestProps) {
|
|
21
|
+
return (
|
|
22
|
+
<Html>
|
|
23
|
+
<Head />
|
|
24
|
+
<Tailwind>
|
|
25
|
+
<Body className="bg-black text-white">
|
|
26
|
+
<Preview>
|
|
27
|
+
Thank you for using our service. We would love to hear your
|
|
28
|
+
feedback.
|
|
29
|
+
</Preview>
|
|
30
|
+
<Container className="mx-auto">
|
|
31
|
+
<Heading className="font-bold text-center my-[48px] text-[32px]">
|
|
32
|
+
Hello {name},
|
|
33
|
+
</Heading>
|
|
34
|
+
<Text>
|
|
35
|
+
Thank you for using our service. We would love to hear your
|
|
36
|
+
thoughts and suggestions.
|
|
37
|
+
</Text>
|
|
38
|
+
<Text>
|
|
39
|
+
We work hard to improve our service and your feedback is crucial
|
|
40
|
+
for us to understand what we are doing well and where we can
|
|
41
|
+
improve.
|
|
42
|
+
</Text>
|
|
43
|
+
<Text className="mb-6">
|
|
44
|
+
If you have any questions about the service or need assistance,
|
|
45
|
+
please feel free to reach out to us at{' '}
|
|
46
|
+
<a
|
|
47
|
+
href="mailto:support@react.email"
|
|
48
|
+
className="text-cyan-300 underline"
|
|
49
|
+
>
|
|
50
|
+
support@react.email
|
|
51
|
+
</a>
|
|
52
|
+
.
|
|
53
|
+
</Text>
|
|
54
|
+
<Row className="w-full">
|
|
55
|
+
<Column className="w-full">
|
|
56
|
+
<Button
|
|
57
|
+
href="https://react.email"
|
|
58
|
+
className="bg-cyan-300 text-[20px] font-bold text-[#404040] w-full text-center border border-solid border-cyan-900 py-[8px] rounded-[8px]"
|
|
59
|
+
>
|
|
60
|
+
Give Feedback
|
|
61
|
+
</Button>
|
|
62
|
+
</Column>
|
|
63
|
+
</Row>
|
|
64
|
+
<Text className="mt-6">- React Email team</Text>
|
|
65
|
+
<Hr style={{ borderTopColor: '#404040' }} />
|
|
66
|
+
<Text className="text-[#606060] font-bold">
|
|
67
|
+
React Email, 999 React St, Email City, EC 12345
|
|
68
|
+
</Text>
|
|
69
|
+
</Container>
|
|
70
|
+
</Body>
|
|
71
|
+
</Tailwind>
|
|
72
|
+
</Html>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
FeedbackRequest.PreviewProps = {
|
|
77
|
+
name: 'user',
|
|
78
|
+
} satisfies FeedbackRequestProps;
|