payload-plugin-newsletter 0.19.0 → 0.20.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/CHANGELOG.md CHANGED
@@ -1,3 +1,58 @@
1
+ ## [0.20.1] - 2025-07-31
2
+
3
+ ### Fixed
4
+ - **Next.js App Router Compatibility** - Fixed React `createContext` error in Next.js App Router
5
+ - Added missing `"use client"` directive to `PluginConfigContext`
6
+ - Added `"use client"` directive to component barrel exports
7
+ - Fixed server-side rendering issues with client components
8
+ - Improved compatibility with Next.js 15+ App Router
9
+
10
+ ### Technical Changes
11
+ - Added `"use client"` directive to `PluginConfigContext.tsx`
12
+ - Added `"use client"` directive to `EmptyField.tsx`
13
+ - Added `"use client"` directive to component index files
14
+ - Ensured proper server/client component separation
15
+
16
+ ## [0.20.0] - 2025-07-31
17
+
18
+ ### Added
19
+ - **Email Preview Customization** - Full control over email preview rendering
20
+ - New `emailPreview` customization options in `BroadcastCustomizations` interface
21
+ - `wrapInTemplate` option to disable default email template wrapping
22
+ - `customWrapper` function for custom email template wrappers
23
+ - Support for both sync and async custom wrapper functions
24
+ - Pass subject and preheader to custom wrapper for complete control
25
+ - `customPreviewComponent` option (planned) for replacing the entire preview component
26
+
27
+ ### Enhanced
28
+ - **Plugin Configuration Context**
29
+ - Added `PluginConfigContext` for passing configuration throughout component tree
30
+ - `usePluginConfig` hook for required config access
31
+ - `usePluginConfigOptional` hook for safe optional config access
32
+ - Context provider integration in component hierarchy
33
+
34
+ - **Email Preview Component**
35
+ - Updated to respect email preview customization options
36
+ - Backward compatible with default template wrapping behavior
37
+ - Support for both prop-based and context-based config passing
38
+ - Seamless integration with custom wrapper functions
39
+
40
+ - **Preview Endpoint**
41
+ - Updated to use email preview customization options
42
+ - Consistent behavior between UI preview and API preview
43
+ - Maintains all existing functionality while adding customization
44
+
45
+ ### Technical Improvements
46
+ - **Type Safety** - Full TypeScript support for all customization options
47
+ - **Backward Compatibility** - All changes maintain 100% backward compatibility
48
+ - **Flexible Architecture** - Easy to extend with additional customization options
49
+ - **Performance** - No performance impact when customization is not used
50
+
51
+ ### Developer Experience
52
+ - **Easy Configuration** - Simple to disable template wrapping or provide custom wrapper
53
+ - **Context Support** - Components can access config without prop drilling
54
+ - **Comprehensive Types** - Well-documented interfaces with examples
55
+
1
56
  ## [0.19.0] - 2025-07-30
2
57
 
3
58
  ### Added
package/README.md CHANGED
@@ -806,6 +806,22 @@ newsletterPlugin({
806
806
  description: 'Custom description'
807
807
  }
808
808
  })
809
+ },
810
+ // Email preview customization (v0.20.0+)
811
+ emailPreview: {
812
+ // Disable default email template wrapping
813
+ wrapInTemplate: false,
814
+
815
+ // Or provide a custom wrapper function
816
+ customWrapper: async (content, { subject, preheader }) => {
817
+ return `
818
+ <div class="my-custom-template">
819
+ <h1>${subject}</h1>
820
+ ${preheader ? `<p class="preheader">${preheader}</p>` : ''}
821
+ <div class="content">${content}</div>
822
+ </div>
823
+ `
824
+ }
809
825
  }
810
826
  }
811
827
  }
@@ -814,6 +830,87 @@ newsletterPlugin({
814
830
 
815
831
  **Note**: Custom blocks are processed server-side to ensure email compatibility and prevent Next.js serialization errors.
816
832
 
833
+ ### Email Preview Customization (v0.20.0+)
834
+
835
+ The plugin now supports full customization of email preview rendering. This is useful when you have custom email templates and want the preview to match what's actually sent.
836
+
837
+ #### Disable Default Template Wrapping
838
+
839
+ If you're using your own email template system, you can disable the default template wrapping:
840
+
841
+ ```typescript
842
+ newsletterPlugin({
843
+ customizations: {
844
+ broadcasts: {
845
+ emailPreview: {
846
+ wrapInTemplate: false // Show raw HTML without email template
847
+ }
848
+ }
849
+ }
850
+ })
851
+ ```
852
+
853
+ #### Custom Email Wrapper
854
+
855
+ Provide your own wrapper function to match your email service's template:
856
+
857
+ ```typescript
858
+ newsletterPlugin({
859
+ customizations: {
860
+ broadcasts: {
861
+ emailPreview: {
862
+ customWrapper: async (content, { subject, preheader }) => {
863
+ // Return your custom email template
864
+ return `
865
+ <!DOCTYPE html>
866
+ <html>
867
+ <head>
868
+ <title>${subject}</title>
869
+ <!-- Your custom styles -->
870
+ </head>
871
+ <body>
872
+ <div class="preheader">${preheader}</div>
873
+ ${content}
874
+ <!-- Your footer -->
875
+ </body>
876
+ </html>
877
+ `
878
+ }
879
+ }
880
+ }
881
+ }
882
+ })
883
+ ```
884
+
885
+ #### Advanced: Using with React Email
886
+
887
+ If you're using React Email for templates, you can integrate it with the preview:
888
+
889
+ ```typescript
890
+ import { render } from '@react-email/render'
891
+ import { MyEmailTemplate } from './emails/MyEmailTemplate'
892
+
893
+ newsletterPlugin({
894
+ customizations: {
895
+ broadcasts: {
896
+ emailPreview: {
897
+ customWrapper: async (content, { subject, preheader }) => {
898
+ return await render(
899
+ <MyEmailTemplate
900
+ subject={subject}
901
+ preheader={preheader}
902
+ content={content}
903
+ />
904
+ )
905
+ }
906
+ }
907
+ }
908
+ }
909
+ })
910
+ ```
911
+
912
+ This ensures your preview exactly matches what subscribers will see.
913
+
817
914
  For complete extensibility documentation, see the [Extension Points Guide](./docs/architecture/extension-points.md).
818
915
 
819
916
  ## Troubleshooting
@@ -976,6 +976,12 @@ async function convertToEmailSafeHtml(editorState, options) {
976
976
  const rawHtml = await lexicalToEmailHtml(editorState, options?.mediaUrl, options?.customBlockConverter);
977
977
  const sanitizedHtml = import_isomorphic_dompurify.default.sanitize(rawHtml, EMAIL_SAFE_CONFIG);
978
978
  if (options?.wrapInTemplate) {
979
+ if (options.customWrapper) {
980
+ return await Promise.resolve(options.customWrapper(sanitizedHtml, {
981
+ preheader: options.preheader,
982
+ subject: options.subject
983
+ }));
984
+ }
979
985
  return wrapInEmailTemplate(sanitizedHtml, options.preheader);
980
986
  }
981
987
  return sanitizedHtml;
@@ -1870,11 +1876,14 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
1870
1876
  const mediaUrl = req.payload.config.serverURL ? `${req.payload.config.serverURL}/api/media` : "/api/media";
1871
1877
  req.payload.logger?.info("Populating media fields for email preview...");
1872
1878
  const populatedContent = await populateMediaFields(content, req.payload, config);
1879
+ const emailPreviewConfig = config.customizations?.broadcasts?.emailPreview;
1873
1880
  const htmlContent = await convertToEmailSafeHtml(populatedContent, {
1874
- wrapInTemplate: true,
1881
+ wrapInTemplate: emailPreviewConfig?.wrapInTemplate ?? true,
1875
1882
  preheader,
1883
+ subject,
1876
1884
  mediaUrl,
1877
- customBlockConverter: config.customizations?.broadcasts?.customBlockConverter
1885
+ customBlockConverter: config.customizations?.broadcasts?.customBlockConverter,
1886
+ customWrapper: emailPreviewConfig?.customWrapper
1878
1887
  });
1879
1888
  return Response.json({
1880
1889
  success: true,