@raypx-kit/email-preview 0.0.0-alpha.0
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/CHANGELOG.md +13 -0
- package/LICENSE +201 -0
- package/README.md +214 -0
- package/dist/THIRD_PARTY_LICENSES.txt +1218 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.mjs +467 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ui/assets/index-BbjBen8c.css +2 -0
- package/dist/ui/assets/index-Hn03Ok93.js +15 -0
- package/dist/ui/index.html +59 -0
- package/examples/_components/footer.tsx +12 -0
- package/examples/account/password-reset.jsx +58 -0
- package/examples/static/mark.svg +5 -0
- package/examples/vite.config.ts +18 -0
- package/examples/welcome.tsx +64 -0
- package/package.json +80 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<script>(function(){
|
|
5
|
+
var options = {"key":"raypx-email-theme","fallback":"system","colors":{"light":"oklch(1 0 0)","dark":"oklch(0.145 0 0)"}};
|
|
6
|
+
function valid(value) { return value === "light" || value === "dark" || value === "system"; }
|
|
7
|
+
var theme = options.fallback;
|
|
8
|
+
if (options.key !== false) {
|
|
9
|
+
var stored;
|
|
10
|
+
try { stored = window.localStorage.getItem(options.key); } catch(e) {}
|
|
11
|
+
if (valid(stored)) theme = stored;
|
|
12
|
+
else {
|
|
13
|
+
try {
|
|
14
|
+
var parts = document.cookie.split(";");
|
|
15
|
+
var key = encodeURIComponent(options.key);
|
|
16
|
+
for (var i = 0; i < parts.length; i++) {
|
|
17
|
+
var split = parts[i].indexOf("=");
|
|
18
|
+
if (split < 0 || parts[i].slice(0, split).trim() !== key) continue;
|
|
19
|
+
var cookie = decodeURIComponent(parts[i].slice(split + 1).trim());
|
|
20
|
+
if (valid(cookie)) theme = cookie;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
} catch(e) {}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (theme === "system") {
|
|
27
|
+
theme = "light";
|
|
28
|
+
try { if (window.matchMedia("(prefers-color-scheme: dark)").matches) theme = "dark"; } catch(e) {}
|
|
29
|
+
}
|
|
30
|
+
var root = document.documentElement;
|
|
31
|
+
root.dataset.theme = theme;
|
|
32
|
+
root.classList.remove("light", "dark");
|
|
33
|
+
root.classList.add(theme);
|
|
34
|
+
root.style.colorScheme = theme;
|
|
35
|
+
var meta = document.querySelector('meta[name="theme-color"]');
|
|
36
|
+
if (!meta) {
|
|
37
|
+
meta = document.createElement("meta");
|
|
38
|
+
meta.setAttribute("name", "theme-color");
|
|
39
|
+
document.head.appendChild(meta);
|
|
40
|
+
}
|
|
41
|
+
meta.setAttribute("content", options.colors[theme]);
|
|
42
|
+
})();</script>
|
|
43
|
+
|
|
44
|
+
<meta charset="utf-8" />
|
|
45
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
46
|
+
<meta name="description" content="Preview and inspect your local React Email templates." />
|
|
47
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
48
|
+
<link
|
|
49
|
+
rel="icon"
|
|
50
|
+
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236d4fc2' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7'/%3E%3C/svg%3E"
|
|
51
|
+
/>
|
|
52
|
+
<title>Email preview · Raypx Kit</title>
|
|
53
|
+
<script type="module" crossorigin src="./assets/index-Hn03Ok93.js"></script>
|
|
54
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BbjBen8c.css">
|
|
55
|
+
</head>
|
|
56
|
+
<body>
|
|
57
|
+
<div id="root"></div>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Hr, Text } from "@react-email/components";
|
|
2
|
+
|
|
3
|
+
export function Footer() {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<Hr style={{ borderColor: "#e7e9ef", marginTop: "32px" }} />
|
|
7
|
+
<Text style={{ color: "#8590a3", fontSize: "12px", lineHeight: "18px" }}>
|
|
8
|
+
Raypx · A little space for your next idea.
|
|
9
|
+
</Text>
|
|
10
|
+
</>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Container,
|
|
5
|
+
Head,
|
|
6
|
+
Heading,
|
|
7
|
+
Html,
|
|
8
|
+
Preview,
|
|
9
|
+
Text,
|
|
10
|
+
} from "@react-email/components";
|
|
11
|
+
import { Footer } from "../_components/footer";
|
|
12
|
+
|
|
13
|
+
export default function PasswordReset({ resetUrl }) {
|
|
14
|
+
return (
|
|
15
|
+
<Html>
|
|
16
|
+
<Head />
|
|
17
|
+
<Preview>A fresh start for your password.</Preview>
|
|
18
|
+
<Body
|
|
19
|
+
style={{
|
|
20
|
+
backgroundColor: "#f4f5f7",
|
|
21
|
+
fontFamily: "Arial, sans-serif",
|
|
22
|
+
padding: "36px 16px",
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<Container
|
|
26
|
+
style={{
|
|
27
|
+
backgroundColor: "#ffffff",
|
|
28
|
+
borderRadius: "12px",
|
|
29
|
+
padding: "36px",
|
|
30
|
+
maxWidth: "560px",
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<Heading style={{ color: "#182033", fontSize: "26px" }}>Reset your password</Heading>
|
|
34
|
+
<Text style={{ color: "#586174", fontSize: "16px", lineHeight: "26px" }}>
|
|
35
|
+
We received a request to reset your password. This link is valid for 30 minutes.
|
|
36
|
+
</Text>
|
|
37
|
+
<Button
|
|
38
|
+
href={resetUrl}
|
|
39
|
+
style={{
|
|
40
|
+
backgroundColor: "#315ee7",
|
|
41
|
+
borderRadius: "8px",
|
|
42
|
+
color: "#ffffff",
|
|
43
|
+
padding: "14px 22px",
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
Choose a new password
|
|
47
|
+
</Button>
|
|
48
|
+
<Text style={{ color: "#586174", fontSize: "14px", lineHeight: "22px" }}>
|
|
49
|
+
If you did not request this, you can safely ignore this email.
|
|
50
|
+
</Text>
|
|
51
|
+
<Footer />
|
|
52
|
+
</Container>
|
|
53
|
+
</Body>
|
|
54
|
+
</Html>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
PasswordReset.PreviewProps = { resetUrl: "https://example.com/reset?token=preview" };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36" role="img" aria-label="Raypx">
|
|
2
|
+
<rect width="36" height="36" rx="10" fill="#315ee7" />
|
|
3
|
+
<path d="M11 25V11h8a5 5 0 0 1 0 10h-4v4zm4-8h4a1 1 0 0 0 0-2h-4z" fill="#fff" />
|
|
4
|
+
<path d="m20 19 6 6h-5l-5-6z" fill="#fff" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { defineConfig } from "vite-plus";
|
|
3
|
+
import { emailPreview } from "../src/index.js";
|
|
4
|
+
import type { InternalOptions } from "../src/server/plugin.js";
|
|
5
|
+
|
|
6
|
+
// Previews these examples with the package source and its built interface.
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
root: fileURLToPath(new URL(".", import.meta.url)),
|
|
9
|
+
resolve: { tsconfigPaths: true },
|
|
10
|
+
server: { host: "127.0.0.1", port: 3001, strictPort: true },
|
|
11
|
+
plugins: [
|
|
12
|
+
emailPreview({
|
|
13
|
+
dir: ".",
|
|
14
|
+
base: "/",
|
|
15
|
+
interfaceDirectory: fileURLToPath(new URL("../dist/ui", import.meta.url)),
|
|
16
|
+
} as InternalOptions),
|
|
17
|
+
],
|
|
18
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Container,
|
|
5
|
+
Head,
|
|
6
|
+
Heading,
|
|
7
|
+
Html,
|
|
8
|
+
Img,
|
|
9
|
+
Preview,
|
|
10
|
+
Text,
|
|
11
|
+
} from "@react-email/components";
|
|
12
|
+
import { Footer } from "./_components/footer";
|
|
13
|
+
|
|
14
|
+
interface WelcomeProps {
|
|
15
|
+
name: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default function Welcome({ name }: WelcomeProps) {
|
|
19
|
+
return (
|
|
20
|
+
<Html>
|
|
21
|
+
<Head />
|
|
22
|
+
<Preview>Your next idea starts here.</Preview>
|
|
23
|
+
<Body
|
|
24
|
+
style={{
|
|
25
|
+
backgroundColor: "#f4f5f7",
|
|
26
|
+
fontFamily: "Arial, sans-serif",
|
|
27
|
+
padding: "36px 16px",
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
<Container
|
|
31
|
+
style={{
|
|
32
|
+
backgroundColor: "#ffffff",
|
|
33
|
+
borderRadius: "12px",
|
|
34
|
+
padding: "36px",
|
|
35
|
+
maxWidth: "560px",
|
|
36
|
+
}}
|
|
37
|
+
>
|
|
38
|
+
<Img src="/static/mark.svg" width="36" height="36" alt="Raypx" />
|
|
39
|
+
<Heading style={{ color: "#182033", fontSize: "28px", marginTop: "28px" }}>
|
|
40
|
+
Welcome, {name}.
|
|
41
|
+
</Heading>
|
|
42
|
+
<Text style={{ color: "#586174", fontSize: "16px", lineHeight: "26px" }}>
|
|
43
|
+
Your workspace is ready. Make a little room for your next big idea.
|
|
44
|
+
</Text>
|
|
45
|
+
<Button
|
|
46
|
+
href="https://example.com/workspace"
|
|
47
|
+
style={{
|
|
48
|
+
backgroundColor: "#315ee7",
|
|
49
|
+
borderRadius: "8px",
|
|
50
|
+
color: "#ffffff",
|
|
51
|
+
padding: "14px 22px",
|
|
52
|
+
marginTop: "12px",
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
Open your workspace
|
|
56
|
+
</Button>
|
|
57
|
+
<Footer />
|
|
58
|
+
</Container>
|
|
59
|
+
</Body>
|
|
60
|
+
</Html>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Welcome.PreviewProps = { name: "Alex" } satisfies WelcomeProps;
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@raypx-kit/email-preview",
|
|
3
|
+
"version": "0.0.0-alpha.0",
|
|
4
|
+
"description": "Preview React Email templates in a Vite dev server or a standalone CLI.",
|
|
5
|
+
"homepage": "https://github.com/raypx/raypx-kit/tree/canary/packages/email-preview",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Zack",
|
|
9
|
+
"email": "heyloyep@gmail.com"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/raypx/raypx-kit.git",
|
|
14
|
+
"directory": "packages/email-preview"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"examples",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"README.md",
|
|
21
|
+
"CHANGELOG.md"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"imports": {
|
|
25
|
+
"#components/*": "./src/ui/components/*.tsx",
|
|
26
|
+
"#lib/*": "./src/ui/lib/*.ts",
|
|
27
|
+
"#hooks/*": "./src/ui/hooks/*.ts"
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.mts",
|
|
32
|
+
"import": "./dist/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"check": "bun --check --tsconfig-override tsconfig.json",
|
|
41
|
+
"build": "tsdown && vp build",
|
|
42
|
+
"dev": "bun run build && vp dev --config examples/vite.config.ts",
|
|
43
|
+
"test": "bun --bun vp test --run",
|
|
44
|
+
"test:unit": "bun --bun vp test --run",
|
|
45
|
+
"pack:check": "bun pm pack --dry-run",
|
|
46
|
+
"test:e2e": "bun ../../e2e/run.ts --project email-preview"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@react-email/render": "^2.1.1",
|
|
50
|
+
"prettier": "^3.9.10"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@playwright/test": "^1.64.1",
|
|
54
|
+
"@raypx-kit/themes": "workspace:*",
|
|
55
|
+
"@raypx-kit/tsconfig": "workspace:*",
|
|
56
|
+
"@raypx-kit/ui": "workspace:*",
|
|
57
|
+
"@react-email/components": "^1.0.12",
|
|
58
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
59
|
+
"@tanstack/react-router": "^1.170.45",
|
|
60
|
+
"@types/node": "^24.19.2",
|
|
61
|
+
"@types/react": "^19.3.0",
|
|
62
|
+
"@types/react-dom": "^19.3.0",
|
|
63
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
64
|
+
"react": "^19.3.1",
|
|
65
|
+
"react-dom": "^19.3.1",
|
|
66
|
+
"tailwindcss": "^4.3.3",
|
|
67
|
+
"tsdown": "^0.23.1",
|
|
68
|
+
"typescript": "^7.0.2",
|
|
69
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@^1.3.0",
|
|
70
|
+
"vite-plus": "^1.3.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"react": "^19.0.0",
|
|
74
|
+
"react-dom": "^19.0.0",
|
|
75
|
+
"vite": "^8.0.0"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=22.21"
|
|
79
|
+
}
|
|
80
|
+
}
|