@ainsleydev/payload-helper 0.0.39 → 0.1.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/README.md +163 -0
- package/dist/admin/components/Icon.d.ts +16 -0
- package/dist/admin/components/Icon.js +26 -0
- package/dist/admin/components/Icon.js.map +1 -0
- package/dist/cli/bin.js +20 -0
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/preview-emails.d.ts +5 -0
- package/dist/cli/commands/preview-emails.js +123 -0
- package/dist/cli/commands/preview-emails.js.map +1 -0
- package/dist/email/ForgotPasswordEmail.d.ts +38 -0
- package/dist/email/ForgotPasswordEmail.js +61 -0
- package/dist/email/ForgotPasswordEmail.js.map +1 -0
- package/dist/email/ForgotPasswordEmail.test.d.ts +1 -0
- package/dist/email/ForgotPasswordEmail.test.js +202 -0
- package/dist/email/ForgotPasswordEmail.test.js.map +1 -0
- package/dist/email/VerifyAccountEmail.d.ts +38 -0
- package/dist/email/VerifyAccountEmail.js +61 -0
- package/dist/email/VerifyAccountEmail.js.map +1 -0
- package/dist/email/VerifyAccountEmail.test.d.ts +1 -0
- package/dist/email/VerifyAccountEmail.test.js +212 -0
- package/dist/email/VerifyAccountEmail.test.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/plugin/admin.d.ts +10 -0
- package/dist/plugin/admin.js +50 -0
- package/dist/plugin/admin.js.map +1 -0
- package/dist/plugin/email.d.ts +10 -0
- package/dist/plugin/email.js +98 -0
- package/dist/plugin/email.js.map +1 -0
- package/dist/plugin/email.test.js +265 -0
- package/dist/plugin/email.test.js.map +1 -0
- package/dist/types.d.ts +147 -1
- package/dist/types.js +3 -1
- package/dist/types.js.map +1 -1
- package/package.json +28 -15
- package/dist/plugin/logo.d.ts +0 -6
- package/dist/plugin/logo.js +0 -26
- package/dist/plugin/logo.js.map +0 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { ForgotPasswordEmail } from './ForgotPasswordEmail.js';
|
|
4
|
+
// Mock the email templates module
|
|
5
|
+
vi.mock('@ainsleydev/email-templates', ()=>({
|
|
6
|
+
BaseEmail: ({ children })=>children,
|
|
7
|
+
Button: ({ children, href })=>/*#__PURE__*/ _jsx("a", {
|
|
8
|
+
href: href,
|
|
9
|
+
children: children
|
|
10
|
+
}),
|
|
11
|
+
Heading: ({ children })=>/*#__PURE__*/ _jsx("h1", {
|
|
12
|
+
children: children
|
|
13
|
+
}),
|
|
14
|
+
Section: ({ children })=>/*#__PURE__*/ _jsx("section", {
|
|
15
|
+
children: children
|
|
16
|
+
}),
|
|
17
|
+
Text: ({ children })=>/*#__PURE__*/ _jsx("p", {
|
|
18
|
+
children: children
|
|
19
|
+
})
|
|
20
|
+
}));
|
|
21
|
+
const mockTheme = {
|
|
22
|
+
colours: {
|
|
23
|
+
text: {
|
|
24
|
+
heading: '#000000',
|
|
25
|
+
body: '#333333',
|
|
26
|
+
action: '#007bff',
|
|
27
|
+
negative: '#ffffff'
|
|
28
|
+
},
|
|
29
|
+
background: {
|
|
30
|
+
white: '#ffffff',
|
|
31
|
+
dark: '#000000',
|
|
32
|
+
darker: '#0f0f0f',
|
|
33
|
+
highlight: '#f5f5f5',
|
|
34
|
+
accent: '#007bff'
|
|
35
|
+
},
|
|
36
|
+
border: {
|
|
37
|
+
light: '#e0e0e0',
|
|
38
|
+
medium: '#cccccc',
|
|
39
|
+
dark: '#000000',
|
|
40
|
+
inverse: '#ffffff'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
branding: {
|
|
44
|
+
companyName: 'Test Company',
|
|
45
|
+
logoUrl: 'https://example.com/logo.png',
|
|
46
|
+
logoWidth: 120,
|
|
47
|
+
websiteUrl: 'https://example.com'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
describe('ForgotPasswordEmail', ()=>{
|
|
51
|
+
test('should render with default content when no overrides provided', ()=>{
|
|
52
|
+
const props = {
|
|
53
|
+
theme: mockTheme,
|
|
54
|
+
user: {
|
|
55
|
+
firstName: 'John',
|
|
56
|
+
email: 'john@example.com'
|
|
57
|
+
},
|
|
58
|
+
resetUrl: 'https://example.com/reset/token123'
|
|
59
|
+
};
|
|
60
|
+
const result = ForgotPasswordEmail(props);
|
|
61
|
+
// Component should render without errors
|
|
62
|
+
expect(result).toBeDefined();
|
|
63
|
+
});
|
|
64
|
+
test('should use firstName when available', ()=>{
|
|
65
|
+
const props = {
|
|
66
|
+
theme: mockTheme,
|
|
67
|
+
user: {
|
|
68
|
+
firstName: 'Jane',
|
|
69
|
+
email: 'jane@example.com'
|
|
70
|
+
},
|
|
71
|
+
resetUrl: 'https://example.com/reset/token123'
|
|
72
|
+
};
|
|
73
|
+
const result = ForgotPasswordEmail(props);
|
|
74
|
+
// The userName should be set to firstName
|
|
75
|
+
// This is tested through the default heading which uses userName
|
|
76
|
+
expect(result).toBeDefined();
|
|
77
|
+
});
|
|
78
|
+
test('should use email when firstName is not available', ()=>{
|
|
79
|
+
const props = {
|
|
80
|
+
theme: mockTheme,
|
|
81
|
+
user: {
|
|
82
|
+
email: 'john@example.com'
|
|
83
|
+
},
|
|
84
|
+
resetUrl: 'https://example.com/reset/token123'
|
|
85
|
+
};
|
|
86
|
+
const result = ForgotPasswordEmail(props);
|
|
87
|
+
// The userName should be set to email
|
|
88
|
+
expect(result).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
test('should use "there" when neither firstName nor email is available', ()=>{
|
|
91
|
+
const props = {
|
|
92
|
+
theme: mockTheme,
|
|
93
|
+
user: {},
|
|
94
|
+
resetUrl: 'https://example.com/reset/token123'
|
|
95
|
+
};
|
|
96
|
+
const result = ForgotPasswordEmail(props);
|
|
97
|
+
// The userName should default to "there"
|
|
98
|
+
expect(result).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
test('should use custom content overrides when provided', ()=>{
|
|
101
|
+
const props = {
|
|
102
|
+
theme: mockTheme,
|
|
103
|
+
user: {
|
|
104
|
+
firstName: 'John'
|
|
105
|
+
},
|
|
106
|
+
resetUrl: 'https://example.com/reset/token123',
|
|
107
|
+
content: {
|
|
108
|
+
previewText: 'Custom preview text',
|
|
109
|
+
heading: 'Custom Heading',
|
|
110
|
+
bodyText: 'Custom body text',
|
|
111
|
+
buttonText: 'Custom Button'
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const result = ForgotPasswordEmail(props);
|
|
115
|
+
// Component should use custom content
|
|
116
|
+
expect(result).toBeDefined();
|
|
117
|
+
});
|
|
118
|
+
test('should use partial content overrides with defaults', ()=>{
|
|
119
|
+
const props = {
|
|
120
|
+
theme: mockTheme,
|
|
121
|
+
user: {
|
|
122
|
+
firstName: 'John'
|
|
123
|
+
},
|
|
124
|
+
resetUrl: 'https://example.com/reset/token123',
|
|
125
|
+
content: {
|
|
126
|
+
heading: 'Custom Heading Only'
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const result = ForgotPasswordEmail(props);
|
|
130
|
+
// Component should use custom heading and default for others
|
|
131
|
+
expect(result).toBeDefined();
|
|
132
|
+
});
|
|
133
|
+
test('should pass resetUrl to the button', ()=>{
|
|
134
|
+
const resetUrl = 'https://example.com/reset/abc123xyz';
|
|
135
|
+
const props = {
|
|
136
|
+
theme: mockTheme,
|
|
137
|
+
user: {
|
|
138
|
+
firstName: 'John'
|
|
139
|
+
},
|
|
140
|
+
resetUrl
|
|
141
|
+
};
|
|
142
|
+
const result = ForgotPasswordEmail(props);
|
|
143
|
+
// The resetUrl should be used in the button href
|
|
144
|
+
expect(result).toBeDefined();
|
|
145
|
+
});
|
|
146
|
+
test('should apply theme colors correctly', ()=>{
|
|
147
|
+
const customTheme = {
|
|
148
|
+
colours: {
|
|
149
|
+
text: {
|
|
150
|
+
heading: '#ff0000',
|
|
151
|
+
body: '#00ff00',
|
|
152
|
+
action: '#0000ff',
|
|
153
|
+
negative: '#ffffff'
|
|
154
|
+
},
|
|
155
|
+
background: {
|
|
156
|
+
white: '#ffffff',
|
|
157
|
+
dark: '#000000',
|
|
158
|
+
darker: '#0f0f0f',
|
|
159
|
+
highlight: '#f5f5f5',
|
|
160
|
+
accent: '#0000ff'
|
|
161
|
+
},
|
|
162
|
+
border: {
|
|
163
|
+
light: '#e0e0e0',
|
|
164
|
+
medium: '#cccccc',
|
|
165
|
+
dark: '#000000',
|
|
166
|
+
inverse: '#ffffff'
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
branding: {
|
|
170
|
+
companyName: 'Custom Company',
|
|
171
|
+
logoUrl: 'https://custom.com/logo.png',
|
|
172
|
+
logoWidth: 150,
|
|
173
|
+
websiteUrl: 'https://custom.com'
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const props = {
|
|
177
|
+
theme: customTheme,
|
|
178
|
+
user: {
|
|
179
|
+
firstName: 'John'
|
|
180
|
+
},
|
|
181
|
+
resetUrl: 'https://example.com/reset/token123'
|
|
182
|
+
};
|
|
183
|
+
const result = ForgotPasswordEmail(props);
|
|
184
|
+
// Component should use custom theme colors
|
|
185
|
+
expect(result).toBeDefined();
|
|
186
|
+
});
|
|
187
|
+
test('should handle empty content object', ()=>{
|
|
188
|
+
const props = {
|
|
189
|
+
theme: mockTheme,
|
|
190
|
+
user: {
|
|
191
|
+
firstName: 'John'
|
|
192
|
+
},
|
|
193
|
+
resetUrl: 'https://example.com/reset/token123',
|
|
194
|
+
content: {}
|
|
195
|
+
};
|
|
196
|
+
const result = ForgotPasswordEmail(props);
|
|
197
|
+
// Should use all defaults when content is empty object
|
|
198
|
+
expect(result).toBeDefined();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
//# sourceMappingURL=ForgotPasswordEmail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/email/ForgotPasswordEmail.test.tsx"],"sourcesContent":["import type { EmailTheme } from '@ainsleydev/email-templates';\nimport { describe, expect, test, vi } from 'vitest';\nimport { ForgotPasswordEmail } from './ForgotPasswordEmail.js';\nimport type { ForgotPasswordEmailProps } from './ForgotPasswordEmail.js';\n\n// Mock the email templates module\nvi.mock('@ainsleydev/email-templates', () => ({\n\tBaseEmail: ({ children }: { children: React.ReactNode }) => children,\n\tButton: ({ children, href }: { children: React.ReactNode; href: string }) => (\n\t\t<a href={href}>{children}</a>\n\t),\n\tHeading: ({ children }: { children: React.ReactNode }) => <h1>{children}</h1>,\n\tSection: ({ children }: { children: React.ReactNode }) => <section>{children}</section>,\n\tText: ({ children }: { children: React.ReactNode }) => <p>{children}</p>,\n}));\n\nconst mockTheme: EmailTheme = {\n\tcolours: {\n\t\ttext: {\n\t\t\theading: '#000000',\n\t\t\tbody: '#333333',\n\t\t\taction: '#007bff',\n\t\t\tnegative: '#ffffff',\n\t\t},\n\t\tbackground: {\n\t\t\twhite: '#ffffff',\n\t\t\tdark: '#000000',\n\t\t\tdarker: '#0f0f0f',\n\t\t\thighlight: '#f5f5f5',\n\t\t\taccent: '#007bff',\n\t\t},\n\t\tborder: {\n\t\t\tlight: '#e0e0e0',\n\t\t\tmedium: '#cccccc',\n\t\t\tdark: '#000000',\n\t\t\tinverse: '#ffffff',\n\t\t},\n\t},\n\tbranding: {\n\t\tcompanyName: 'Test Company',\n\t\tlogoUrl: 'https://example.com/logo.png',\n\t\tlogoWidth: 120,\n\t\twebsiteUrl: 'https://example.com',\n\t},\n};\n\ndescribe('ForgotPasswordEmail', () => {\n\ttest('should render with default content when no overrides provided', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// Component should render without errors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use firstName when available', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'Jane',\n\t\t\t\temail: 'jane@example.com',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// The userName should be set to firstName\n\t\t// This is tested through the default heading which uses userName\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use email when firstName is not available', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// The userName should be set to email\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use \"there\" when neither firstName nor email is available', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// The userName should default to \"there\"\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use custom content overrides when provided', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t\tcontent: {\n\t\t\t\tpreviewText: 'Custom preview text',\n\t\t\t\theading: 'Custom Heading',\n\t\t\t\tbodyText: 'Custom body text',\n\t\t\t\tbuttonText: 'Custom Button',\n\t\t\t},\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// Component should use custom content\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use partial content overrides with defaults', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t\tcontent: {\n\t\t\t\theading: 'Custom Heading Only',\n\t\t\t\t// Other fields should use defaults\n\t\t\t},\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// Component should use custom heading and default for others\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should pass resetUrl to the button', () => {\n\t\tconst resetUrl = 'https://example.com/reset/abc123xyz';\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tresetUrl,\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// The resetUrl should be used in the button href\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should apply theme colors correctly', () => {\n\t\tconst customTheme: EmailTheme = {\n\t\t\tcolours: {\n\t\t\t\ttext: {\n\t\t\t\t\theading: '#ff0000',\n\t\t\t\t\tbody: '#00ff00',\n\t\t\t\t\taction: '#0000ff',\n\t\t\t\t\tnegative: '#ffffff',\n\t\t\t\t},\n\t\t\t\tbackground: {\n\t\t\t\t\twhite: '#ffffff',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tdarker: '#0f0f0f',\n\t\t\t\t\thighlight: '#f5f5f5',\n\t\t\t\t\taccent: '#0000ff',\n\t\t\t\t},\n\t\t\t\tborder: {\n\t\t\t\t\tlight: '#e0e0e0',\n\t\t\t\t\tmedium: '#cccccc',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tinverse: '#ffffff',\n\t\t\t\t},\n\t\t\t},\n\t\t\tbranding: {\n\t\t\t\tcompanyName: 'Custom Company',\n\t\t\t\tlogoUrl: 'https://custom.com/logo.png',\n\t\t\t\tlogoWidth: 150,\n\t\t\t\twebsiteUrl: 'https://custom.com',\n\t\t\t},\n\t\t};\n\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: customTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// Component should use custom theme colors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should handle empty content object', () => {\n\t\tconst props: ForgotPasswordEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tresetUrl: 'https://example.com/reset/token123',\n\t\t\tcontent: {},\n\t\t};\n\n\t\tconst result = ForgotPasswordEmail(props);\n\n\t\t// Should use all defaults when content is empty object\n\t\texpect(result).toBeDefined();\n\t});\n});\n"],"names":["describe","expect","test","vi","ForgotPasswordEmail","mock","BaseEmail","children","Button","href","a","Heading","h1","Section","section","Text","p","mockTheme","colours","text","heading","body","action","negative","background","white","dark","darker","highlight","accent","border","light","medium","inverse","branding","companyName","logoUrl","logoWidth","websiteUrl","props","theme","user","firstName","email","resetUrl","result","toBeDefined","content","previewText","bodyText","buttonText","customTheme"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { EmailTheme } from '@ainsleydev/email-templates';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Props for the VerifyAccountEmail component.
|
|
5
|
+
*/
|
|
6
|
+
export interface VerifyAccountEmailProps {
|
|
7
|
+
/**
|
|
8
|
+
* The email theme (required by renderEmail).
|
|
9
|
+
*/
|
|
10
|
+
theme: EmailTheme;
|
|
11
|
+
/**
|
|
12
|
+
* The user object containing user information.
|
|
13
|
+
*/
|
|
14
|
+
user: {
|
|
15
|
+
firstName?: string;
|
|
16
|
+
email?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The URL for verifying the account.
|
|
20
|
+
*/
|
|
21
|
+
verifyUrl: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional content overrides.
|
|
24
|
+
*/
|
|
25
|
+
content?: {
|
|
26
|
+
previewText?: string;
|
|
27
|
+
heading?: string;
|
|
28
|
+
bodyText?: string;
|
|
29
|
+
buttonText?: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Email template for account verification in Payload CMS.
|
|
34
|
+
*
|
|
35
|
+
* @param props - The component props
|
|
36
|
+
* @returns The rendered email component
|
|
37
|
+
*/
|
|
38
|
+
export declare const VerifyAccountEmail: ({ theme, user, verifyUrl, content, }: VerifyAccountEmailProps) => React.JSX.Element;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BaseEmail, Button, Heading, Section, Text } from '@ainsleydev/email-templates';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Email template for account verification in Payload CMS.
|
|
6
|
+
*
|
|
7
|
+
* @param props - The component props
|
|
8
|
+
* @returns The rendered email component
|
|
9
|
+
*/ export const VerifyAccountEmail = ({ theme, user, verifyUrl, content })=>{
|
|
10
|
+
const userName = user.firstName || user.email || 'there';
|
|
11
|
+
const previewText = content?.previewText || 'Verify your email';
|
|
12
|
+
const heading = content?.heading || `Welcome, ${userName}!`;
|
|
13
|
+
const bodyText = content?.bodyText || 'Please verify your email by clicking the button below. If you did not request a password reset, you can safely ignore this email.';
|
|
14
|
+
const buttonText = content?.buttonText || 'Verify Email';
|
|
15
|
+
return /*#__PURE__*/ _jsxs(BaseEmail, {
|
|
16
|
+
theme: theme,
|
|
17
|
+
previewText: previewText,
|
|
18
|
+
children: [
|
|
19
|
+
/*#__PURE__*/ _jsx(Heading, {
|
|
20
|
+
style: {
|
|
21
|
+
color: theme.colours.text.heading,
|
|
22
|
+
fontSize: '24px',
|
|
23
|
+
fontWeight: 'bold',
|
|
24
|
+
marginBottom: '20px'
|
|
25
|
+
},
|
|
26
|
+
children: heading
|
|
27
|
+
}),
|
|
28
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
29
|
+
style: {
|
|
30
|
+
color: theme.colours.text.body,
|
|
31
|
+
fontSize: '16px',
|
|
32
|
+
lineHeight: '24px',
|
|
33
|
+
marginBottom: '30px'
|
|
34
|
+
},
|
|
35
|
+
children: bodyText
|
|
36
|
+
}),
|
|
37
|
+
/*#__PURE__*/ _jsx(Section, {
|
|
38
|
+
style: {
|
|
39
|
+
textAlign: 'center',
|
|
40
|
+
marginBottom: '30px'
|
|
41
|
+
},
|
|
42
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
43
|
+
href: verifyUrl,
|
|
44
|
+
style: {
|
|
45
|
+
backgroundColor: theme.colours.background.accent,
|
|
46
|
+
color: theme.colours.text.heading,
|
|
47
|
+
padding: '12px 32px',
|
|
48
|
+
borderRadius: '5px',
|
|
49
|
+
fontSize: '16px',
|
|
50
|
+
fontWeight: 'bold',
|
|
51
|
+
textDecoration: 'none',
|
|
52
|
+
display: 'inline-block'
|
|
53
|
+
},
|
|
54
|
+
children: buttonText
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=VerifyAccountEmail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/email/VerifyAccountEmail.tsx"],"sourcesContent":["import { BaseEmail, Button, Heading, Section, Text } from '@ainsleydev/email-templates';\nimport type { EmailTheme } from '@ainsleydev/email-templates';\nimport * as React from 'react';\n\n/**\n * Props for the VerifyAccountEmail component.\n */\nexport interface VerifyAccountEmailProps {\n\t/**\n\t * The email theme (required by renderEmail).\n\t */\n\ttheme: EmailTheme;\n\n\t/**\n\t * The user object containing user information.\n\t */\n\tuser: {\n\t\tfirstName?: string;\n\t\temail?: string;\n\t};\n\n\t/**\n\t * The URL for verifying the account.\n\t */\n\tverifyUrl: string;\n\n\t/**\n\t * Optional content overrides.\n\t */\n\tcontent?: {\n\t\tpreviewText?: string;\n\t\theading?: string;\n\t\tbodyText?: string;\n\t\tbuttonText?: string;\n\t};\n}\n\n/**\n * Email template for account verification in Payload CMS.\n *\n * @param props - The component props\n * @returns The rendered email component\n */\nexport const VerifyAccountEmail = ({\n\ttheme,\n\tuser,\n\tverifyUrl,\n\tcontent,\n}: VerifyAccountEmailProps) => {\n\tconst userName = user.firstName || user.email || 'there';\n\tconst previewText = content?.previewText || 'Verify your email';\n\tconst heading = content?.heading || `Welcome, ${userName}!`;\n\tconst bodyText =\n\t\tcontent?.bodyText ||\n\t\t'Please verify your email by clicking the button below. If you did not request a password reset, you can safely ignore this email.';\n\tconst buttonText = content?.buttonText || 'Verify Email';\n\n\treturn (\n\t\t<BaseEmail theme={theme} previewText={previewText}>\n\t\t\t<Heading\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: theme.colours.text.heading,\n\t\t\t\t\tfontSize: '24px',\n\t\t\t\t\tfontWeight: 'bold',\n\t\t\t\t\tmarginBottom: '20px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{heading}\n\t\t\t</Heading>\n\t\t\t<Text\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: theme.colours.text.body,\n\t\t\t\t\tfontSize: '16px',\n\t\t\t\t\tlineHeight: '24px',\n\t\t\t\t\tmarginBottom: '30px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{bodyText}\n\t\t\t</Text>\n\t\t\t<Section style={{ textAlign: 'center', marginBottom: '30px' }}>\n\t\t\t\t<Button\n\t\t\t\t\thref={verifyUrl}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackgroundColor: theme.colours.background.accent,\n\t\t\t\t\t\tcolor: theme.colours.text.heading,\n\t\t\t\t\t\tpadding: '12px 32px',\n\t\t\t\t\t\tborderRadius: '5px',\n\t\t\t\t\t\tfontSize: '16px',\n\t\t\t\t\t\tfontWeight: 'bold',\n\t\t\t\t\t\ttextDecoration: 'none',\n\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{buttonText}\n\t\t\t\t</Button>\n\t\t\t</Section>\n\t\t</BaseEmail>\n\t);\n};\n"],"names":["BaseEmail","Button","Heading","Section","Text","React","VerifyAccountEmail","theme","user","verifyUrl","content","userName","firstName","email","previewText","heading","bodyText","buttonText","style","color","colours","text","fontSize","fontWeight","marginBottom","body","lineHeight","textAlign","href","backgroundColor","background","accent","padding","borderRadius","textDecoration","display"],"mappings":";AAAA,SAASA,SAAS,EAAEC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEC,IAAI,QAAQ,8BAA8B;AAExF,YAAYC,WAAW,QAAQ;AAmC/B;;;;;CAKC,GACD,OAAO,MAAMC,qBAAqB,CAAC,EAClCC,KAAK,EACLC,IAAI,EACJC,SAAS,EACTC,OAAO,EACkB;IACzB,MAAMC,WAAWH,KAAKI,SAAS,IAAIJ,KAAKK,KAAK,IAAI;IACjD,MAAMC,cAAcJ,SAASI,eAAe;IAC5C,MAAMC,UAAUL,SAASK,WAAW,CAAC,SAAS,EAAEJ,SAAS,CAAC,CAAC;IAC3D,MAAMK,WACLN,SAASM,YACT;IACD,MAAMC,aAAaP,SAASO,cAAc;IAE1C,qBACC,MAACjB;QAAUO,OAAOA;QAAOO,aAAaA;;0BACrC,KAACZ;gBACAgB,OAAO;oBACNC,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACN,OAAO;oBACjCO,UAAU;oBACVC,YAAY;oBACZC,cAAc;gBACf;0BAECT;;0BAEF,KAACX;gBACAc,OAAO;oBACNC,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACI,IAAI;oBAC9BH,UAAU;oBACVI,YAAY;oBACZF,cAAc;gBACf;0BAECR;;0BAEF,KAACb;gBAAQe,OAAO;oBAAES,WAAW;oBAAUH,cAAc;gBAAO;0BAC3D,cAAA,KAACvB;oBACA2B,MAAMnB;oBACNS,OAAO;wBACNW,iBAAiBtB,MAAMa,OAAO,CAACU,UAAU,CAACC,MAAM;wBAChDZ,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACN,OAAO;wBACjCiB,SAAS;wBACTC,cAAc;wBACdX,UAAU;wBACVC,YAAY;wBACZW,gBAAgB;wBAChBC,SAAS;oBACV;8BAEClB;;;;;AAKN,EAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { VerifyAccountEmail } from './VerifyAccountEmail.js';
|
|
4
|
+
// Mock the email templates module
|
|
5
|
+
vi.mock('@ainsleydev/email-templates', ()=>({
|
|
6
|
+
BaseEmail: ({ children })=>children,
|
|
7
|
+
Button: ({ children, href })=>/*#__PURE__*/ _jsx("a", {
|
|
8
|
+
href: href,
|
|
9
|
+
children: children
|
|
10
|
+
}),
|
|
11
|
+
Heading: ({ children })=>/*#__PURE__*/ _jsx("h1", {
|
|
12
|
+
children: children
|
|
13
|
+
}),
|
|
14
|
+
Section: ({ children })=>/*#__PURE__*/ _jsx("section", {
|
|
15
|
+
children: children
|
|
16
|
+
}),
|
|
17
|
+
Text: ({ children })=>/*#__PURE__*/ _jsx("p", {
|
|
18
|
+
children: children
|
|
19
|
+
})
|
|
20
|
+
}));
|
|
21
|
+
const mockTheme = {
|
|
22
|
+
colours: {
|
|
23
|
+
text: {
|
|
24
|
+
heading: '#000000',
|
|
25
|
+
body: '#333333',
|
|
26
|
+
action: '#007bff',
|
|
27
|
+
negative: '#ffffff'
|
|
28
|
+
},
|
|
29
|
+
background: {
|
|
30
|
+
white: '#ffffff',
|
|
31
|
+
dark: '#000000',
|
|
32
|
+
darker: '#0f0f0f',
|
|
33
|
+
highlight: '#f5f5f5',
|
|
34
|
+
accent: '#007bff'
|
|
35
|
+
},
|
|
36
|
+
border: {
|
|
37
|
+
light: '#e0e0e0',
|
|
38
|
+
medium: '#cccccc',
|
|
39
|
+
dark: '#000000',
|
|
40
|
+
inverse: '#ffffff'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
branding: {
|
|
44
|
+
companyName: 'Test Company',
|
|
45
|
+
logoUrl: 'https://example.com/logo.png',
|
|
46
|
+
logoWidth: 120,
|
|
47
|
+
websiteUrl: 'https://example.com'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
describe('VerifyAccountEmail', ()=>{
|
|
51
|
+
test('should render with default content when no overrides provided', ()=>{
|
|
52
|
+
const props = {
|
|
53
|
+
theme: mockTheme,
|
|
54
|
+
user: {
|
|
55
|
+
firstName: 'John',
|
|
56
|
+
email: 'john@example.com'
|
|
57
|
+
},
|
|
58
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
59
|
+
};
|
|
60
|
+
const result = VerifyAccountEmail(props);
|
|
61
|
+
// Component should render without errors
|
|
62
|
+
expect(result).toBeDefined();
|
|
63
|
+
});
|
|
64
|
+
test('should use firstName when available', ()=>{
|
|
65
|
+
const props = {
|
|
66
|
+
theme: mockTheme,
|
|
67
|
+
user: {
|
|
68
|
+
firstName: 'Jane',
|
|
69
|
+
email: 'jane@example.com'
|
|
70
|
+
},
|
|
71
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
72
|
+
};
|
|
73
|
+
const result = VerifyAccountEmail(props);
|
|
74
|
+
// The userName should be set to firstName
|
|
75
|
+
// This is tested through the default heading which uses userName
|
|
76
|
+
expect(result).toBeDefined();
|
|
77
|
+
});
|
|
78
|
+
test('should use email when firstName is not available', ()=>{
|
|
79
|
+
const props = {
|
|
80
|
+
theme: mockTheme,
|
|
81
|
+
user: {
|
|
82
|
+
email: 'john@example.com'
|
|
83
|
+
},
|
|
84
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
85
|
+
};
|
|
86
|
+
const result = VerifyAccountEmail(props);
|
|
87
|
+
// The userName should be set to email
|
|
88
|
+
expect(result).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
test('should use "there" when neither firstName nor email is available', ()=>{
|
|
91
|
+
const props = {
|
|
92
|
+
theme: mockTheme,
|
|
93
|
+
user: {},
|
|
94
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
95
|
+
};
|
|
96
|
+
const result = VerifyAccountEmail(props);
|
|
97
|
+
// The userName should default to "there"
|
|
98
|
+
expect(result).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
test('should use custom content overrides when provided', ()=>{
|
|
101
|
+
const props = {
|
|
102
|
+
theme: mockTheme,
|
|
103
|
+
user: {
|
|
104
|
+
firstName: 'John'
|
|
105
|
+
},
|
|
106
|
+
verifyUrl: 'https://example.com/verify/token123',
|
|
107
|
+
content: {
|
|
108
|
+
previewText: 'Custom preview text',
|
|
109
|
+
heading: 'Custom Welcome Heading',
|
|
110
|
+
bodyText: 'Custom verification message',
|
|
111
|
+
buttonText: 'Custom Verify Button'
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const result = VerifyAccountEmail(props);
|
|
115
|
+
// Component should use custom content
|
|
116
|
+
expect(result).toBeDefined();
|
|
117
|
+
});
|
|
118
|
+
test('should use partial content overrides with defaults', ()=>{
|
|
119
|
+
const props = {
|
|
120
|
+
theme: mockTheme,
|
|
121
|
+
user: {
|
|
122
|
+
firstName: 'John'
|
|
123
|
+
},
|
|
124
|
+
verifyUrl: 'https://example.com/verify/token123',
|
|
125
|
+
content: {
|
|
126
|
+
buttonText: 'Confirm Email'
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const result = VerifyAccountEmail(props);
|
|
130
|
+
// Component should use custom button text and defaults for others
|
|
131
|
+
expect(result).toBeDefined();
|
|
132
|
+
});
|
|
133
|
+
test('should pass verifyUrl to the button', ()=>{
|
|
134
|
+
const verifyUrl = 'https://example.com/verify/xyz789abc';
|
|
135
|
+
const props = {
|
|
136
|
+
theme: mockTheme,
|
|
137
|
+
user: {
|
|
138
|
+
firstName: 'John'
|
|
139
|
+
},
|
|
140
|
+
verifyUrl
|
|
141
|
+
};
|
|
142
|
+
const result = VerifyAccountEmail(props);
|
|
143
|
+
// The verifyUrl should be used in the button href
|
|
144
|
+
expect(result).toBeDefined();
|
|
145
|
+
});
|
|
146
|
+
test('should apply theme colors correctly', ()=>{
|
|
147
|
+
const customTheme = {
|
|
148
|
+
colours: {
|
|
149
|
+
text: {
|
|
150
|
+
heading: '#ff0000',
|
|
151
|
+
body: '#00ff00',
|
|
152
|
+
action: '#0000ff',
|
|
153
|
+
negative: '#ffffff'
|
|
154
|
+
},
|
|
155
|
+
background: {
|
|
156
|
+
white: '#ffffff',
|
|
157
|
+
dark: '#000000',
|
|
158
|
+
darker: '#0f0f0f',
|
|
159
|
+
highlight: '#f5f5f5',
|
|
160
|
+
accent: '#0000ff'
|
|
161
|
+
},
|
|
162
|
+
border: {
|
|
163
|
+
light: '#e0e0e0',
|
|
164
|
+
medium: '#cccccc',
|
|
165
|
+
dark: '#000000',
|
|
166
|
+
inverse: '#ffffff'
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
branding: {
|
|
170
|
+
companyName: 'Custom Company',
|
|
171
|
+
logoUrl: 'https://custom.com/logo.png',
|
|
172
|
+
logoWidth: 150,
|
|
173
|
+
websiteUrl: 'https://custom.com'
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
const props = {
|
|
177
|
+
theme: customTheme,
|
|
178
|
+
user: {
|
|
179
|
+
firstName: 'John'
|
|
180
|
+
},
|
|
181
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
182
|
+
};
|
|
183
|
+
const result = VerifyAccountEmail(props);
|
|
184
|
+
// Component should use custom theme colors
|
|
185
|
+
expect(result).toBeDefined();
|
|
186
|
+
});
|
|
187
|
+
test('should handle empty content object', ()=>{
|
|
188
|
+
const props = {
|
|
189
|
+
theme: mockTheme,
|
|
190
|
+
user: {
|
|
191
|
+
firstName: 'John'
|
|
192
|
+
},
|
|
193
|
+
verifyUrl: 'https://example.com/verify/token123',
|
|
194
|
+
content: {}
|
|
195
|
+
};
|
|
196
|
+
const result = VerifyAccountEmail(props);
|
|
197
|
+
// Should use all defaults when content is empty object
|
|
198
|
+
expect(result).toBeDefined();
|
|
199
|
+
});
|
|
200
|
+
test('should render with minimal props', ()=>{
|
|
201
|
+
const props = {
|
|
202
|
+
theme: mockTheme,
|
|
203
|
+
user: {},
|
|
204
|
+
verifyUrl: 'https://example.com/verify/token123'
|
|
205
|
+
};
|
|
206
|
+
const result = VerifyAccountEmail(props);
|
|
207
|
+
// Should handle minimal props gracefully
|
|
208
|
+
expect(result).toBeDefined();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
//# sourceMappingURL=VerifyAccountEmail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/email/VerifyAccountEmail.test.tsx"],"sourcesContent":["import type { EmailTheme } from '@ainsleydev/email-templates';\nimport { describe, expect, test, vi } from 'vitest';\nimport { VerifyAccountEmail } from './VerifyAccountEmail.js';\nimport type { VerifyAccountEmailProps } from './VerifyAccountEmail.js';\n\n// Mock the email templates module\nvi.mock('@ainsleydev/email-templates', () => ({\n\tBaseEmail: ({ children }: { children: React.ReactNode }) => children,\n\tButton: ({ children, href }: { children: React.ReactNode; href: string }) => (\n\t\t<a href={href}>{children}</a>\n\t),\n\tHeading: ({ children }: { children: React.ReactNode }) => <h1>{children}</h1>,\n\tSection: ({ children }: { children: React.ReactNode }) => <section>{children}</section>,\n\tText: ({ children }: { children: React.ReactNode }) => <p>{children}</p>,\n}));\n\nconst mockTheme: EmailTheme = {\n\tcolours: {\n\t\ttext: {\n\t\t\theading: '#000000',\n\t\t\tbody: '#333333',\n\t\t\taction: '#007bff',\n\t\t\tnegative: '#ffffff',\n\t\t},\n\t\tbackground: {\n\t\t\twhite: '#ffffff',\n\t\t\tdark: '#000000',\n\t\t\tdarker: '#0f0f0f',\n\t\t\thighlight: '#f5f5f5',\n\t\t\taccent: '#007bff',\n\t\t},\n\t\tborder: {\n\t\t\tlight: '#e0e0e0',\n\t\t\tmedium: '#cccccc',\n\t\t\tdark: '#000000',\n\t\t\tinverse: '#ffffff',\n\t\t},\n\t},\n\tbranding: {\n\t\tcompanyName: 'Test Company',\n\t\tlogoUrl: 'https://example.com/logo.png',\n\t\tlogoWidth: 120,\n\t\twebsiteUrl: 'https://example.com',\n\t},\n};\n\ndescribe('VerifyAccountEmail', () => {\n\ttest('should render with default content when no overrides provided', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should render without errors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use firstName when available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'Jane',\n\t\t\t\temail: 'jane@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should be set to firstName\n\t\t// This is tested through the default heading which uses userName\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use email when firstName is not available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should be set to email\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use \"there\" when neither firstName nor email is available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should default to \"there\"\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use custom content overrides when provided', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {\n\t\t\t\tpreviewText: 'Custom preview text',\n\t\t\t\theading: 'Custom Welcome Heading',\n\t\t\t\tbodyText: 'Custom verification message',\n\t\t\t\tbuttonText: 'Custom Verify Button',\n\t\t\t},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom content\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use partial content overrides with defaults', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {\n\t\t\t\tbuttonText: 'Confirm Email',\n\t\t\t\t// Other fields should use defaults\n\t\t\t},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom button text and defaults for others\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should pass verifyUrl to the button', () => {\n\t\tconst verifyUrl = 'https://example.com/verify/xyz789abc';\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl,\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The verifyUrl should be used in the button href\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should apply theme colors correctly', () => {\n\t\tconst customTheme: EmailTheme = {\n\t\t\tcolours: {\n\t\t\t\ttext: {\n\t\t\t\t\theading: '#ff0000',\n\t\t\t\t\tbody: '#00ff00',\n\t\t\t\t\taction: '#0000ff',\n\t\t\t\t\tnegative: '#ffffff',\n\t\t\t\t},\n\t\t\t\tbackground: {\n\t\t\t\t\twhite: '#ffffff',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tdarker: '#0f0f0f',\n\t\t\t\t\thighlight: '#f5f5f5',\n\t\t\t\t\taccent: '#0000ff',\n\t\t\t\t},\n\t\t\t\tborder: {\n\t\t\t\t\tlight: '#e0e0e0',\n\t\t\t\t\tmedium: '#cccccc',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tinverse: '#ffffff',\n\t\t\t\t},\n\t\t\t},\n\t\t\tbranding: {\n\t\t\t\tcompanyName: 'Custom Company',\n\t\t\t\tlogoUrl: 'https://custom.com/logo.png',\n\t\t\t\tlogoWidth: 150,\n\t\t\t\twebsiteUrl: 'https://custom.com',\n\t\t\t},\n\t\t};\n\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: customTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom theme colors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should handle empty content object', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Should use all defaults when content is empty object\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should render with minimal props', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Should handle minimal props gracefully\n\t\texpect(result).toBeDefined();\n\t});\n});\n"],"names":["describe","expect","test","vi","VerifyAccountEmail","mock","BaseEmail","children","Button","href","a","Heading","h1","Section","section","Text","p","mockTheme","colours","text","heading","body","action","negative","background","white","dark","darker","highlight","accent","border","light","medium","inverse","branding","companyName","logoUrl","logoWidth","websiteUrl","props","theme","user","firstName","email","verifyUrl","result","toBeDefined","content","previewText","bodyText","buttonText","customTheme"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,11 @@ import type { PayloadHelperPluginConfig } from './types.js';
|
|
|
7
7
|
* @param pluginOptions
|
|
8
8
|
*/
|
|
9
9
|
export declare const payloadHelper: (pluginOptions: PayloadHelperPluginConfig) => (incomingConfig: Config) => Config;
|
|
10
|
+
export type { IconProps } from './admin/components/Icon.js';
|
|
10
11
|
export type { LogoProps } from './admin/components/Logo.js';
|
|
11
|
-
export
|
|
12
|
+
export { ForgotPasswordEmail } from './email/ForgotPasswordEmail.js';
|
|
13
|
+
export type { ForgotPasswordEmailProps } from './email/ForgotPasswordEmail.js';
|
|
14
|
+
export { VerifyAccountEmail } from './email/VerifyAccountEmail.js';
|
|
15
|
+
export type { VerifyAccountEmailProps } from './email/VerifyAccountEmail.js';
|
|
16
|
+
export { default as env } from './util/env.js';
|
|
17
|
+
export type { AdminConfig, AdminIconConfig, AdminLogoConfig, EmailConfig, EmailContentOverrides, PayloadHelperPluginConfig, } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { injectAdminIcon, injectAdminLogo } from './plugin/admin.js';
|
|
2
|
+
import { injectEmailTemplates } from './plugin/email.js';
|
|
1
3
|
import { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';
|
|
2
|
-
import { injectAdminLogo } from './plugin/logo.js';
|
|
3
4
|
/**
|
|
4
5
|
* Payload Helper Plugin for websites at ainsley.dev
|
|
5
6
|
*
|
|
@@ -11,9 +12,17 @@ import { injectAdminLogo } from './plugin/logo.js';
|
|
|
11
12
|
// Update typescript generation file
|
|
12
13
|
config.typescript = config.typescript || {};
|
|
13
14
|
config.typescript.outputFile = './src/types/payload.ts';
|
|
14
|
-
// Inject admin Logo component if
|
|
15
|
-
if (pluginOptions.
|
|
16
|
-
config = injectAdminLogo(config, pluginOptions.
|
|
15
|
+
// Inject admin Logo component if logo config is provided
|
|
16
|
+
if (pluginOptions.admin?.logo) {
|
|
17
|
+
config = injectAdminLogo(config, pluginOptions.admin.logo, pluginOptions.siteName);
|
|
18
|
+
}
|
|
19
|
+
// Inject admin Icon component if icon config is provided
|
|
20
|
+
if (pluginOptions.admin?.icon) {
|
|
21
|
+
config = injectAdminIcon(config, pluginOptions.admin.icon, pluginOptions.siteName);
|
|
22
|
+
}
|
|
23
|
+
// Inject email templates for auth-enabled collections if email config is provided
|
|
24
|
+
if (pluginOptions.email) {
|
|
25
|
+
config = injectEmailTemplates(config, pluginOptions.email);
|
|
17
26
|
}
|
|
18
27
|
// Map collections & add hooks
|
|
19
28
|
config.collections = (config.collections || []).map((collection)=>{
|
|
@@ -58,7 +67,15 @@ import { injectAdminLogo } from './plugin/logo.js';
|
|
|
58
67
|
hooks
|
|
59
68
|
};
|
|
60
69
|
});
|
|
70
|
+
// Store plugin options in config.custom for CLI access (e.g., preview-emails command)
|
|
71
|
+
config.custom = {
|
|
72
|
+
...config.custom,
|
|
73
|
+
payloadHelperOptions: pluginOptions
|
|
74
|
+
};
|
|
61
75
|
return config;
|
|
62
76
|
};
|
|
77
|
+
export { ForgotPasswordEmail } from './email/ForgotPasswordEmail.js';
|
|
78
|
+
export { VerifyAccountEmail } from './email/VerifyAccountEmail.js';
|
|
79
|
+
export { default as env } from './util/env.js';
|
|
63
80
|
|
|
64
81
|
//# sourceMappingURL=index.js.map
|