payload-plugin-newsletter 0.20.3 → 0.20.5

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,68 @@
1
+ ## [0.20.5] - 2025-08-01
2
+
3
+ ### Fixed
4
+ - **Manual Preview Button** - Replaced automatic preview with manual "Generate Preview" button
5
+ - Fixed content access issue where preview couldn't find content due to field group separation
6
+ - Changed from `data.content` to `fields?.contentSection?.content` using `useFormFields` hook
7
+ - Removed automatic hot-reloading in favor of user-controlled preview generation
8
+ - Added "Hide Preview" and "Refresh Preview" buttons for better control
9
+ - Preview now correctly accesses content from nested field groups
10
+
11
+ ### Enhanced
12
+ - **Better Error Handling** - Clear error messages when no content is available
13
+ - **Improved UX** - Manual preview button prevents excessive API calls during content editing
14
+ - **Proper Form Data Access** - Uses Payload's `useFormFields` hook to access all form fields across groups
15
+
16
+ ### Technical Changes
17
+ - Component now implements `UIFieldClientComponent` interface from Payload
18
+ - Removed automatic `useEffect` triggers and debouncing
19
+ - Fixed field path from `data.content` to `fields?.contentSection?.content`
20
+ - Maintains 600px iframe height for consistent preview display
21
+
22
+ ## [0.20.4] - 2025-07-31
23
+
24
+ ### Added
25
+ - **Email Preview Functionality Restored** - Full email preview functionality in admin interface
26
+ - Interactive preview component with live content updates
27
+ - Real-time iframe rendering of email HTML using the preview endpoint
28
+ - Debounced API calls to prevent excessive requests during content editing
29
+ - Auto-resizing iframe that adjusts to email content height
30
+ - Comprehensive error handling with user-friendly error messages
31
+ - Loading states and empty content placeholders for better UX
32
+ - Subject line display in preview header
33
+ - Preview updates automatically when content, subject, or preheader changes
34
+
35
+ ### Enhanced
36
+ - **BroadcastInlinePreview Component**
37
+ - Replaced placeholder component with fully functional preview
38
+ - Added React hooks for state management (useState, useEffect, useRef)
39
+ - Integrated with existing `/api/broadcasts/preview` endpoint
40
+ - Added proper TypeScript types and interfaces
41
+ - Includes responsive iframe with cross-origin safety measures
42
+ - 500ms debounce to optimize API calls during content editing
43
+
44
+ ### Fixed
45
+ - **Preview Endpoint Response Format** - Updated to include both `html` and `preview.html` fields for compatibility
46
+ - **ESLint Compliance** - Resolved all linting errors in admin components
47
+ - **Admin Bundle Integrity** - Maintained separation of server dependencies while restoring functionality
48
+
49
+ ### Technical Changes
50
+ - Updated admin component exports to use direct type imports from components
51
+ - Removed redundant admin/types.ts file in favor of component-level type exports
52
+ - Enhanced preview endpoint to return HTML in multiple response formats
53
+ - Added proper error boundaries and loading states in preview component
54
+ - Maintained all architectural improvements from v0.20.3 bundle separation
55
+
56
+ ### Validation
57
+ - ✅ Preview component fetches and displays email HTML correctly
58
+ - ✅ Preview updates in real-time as content changes
59
+ - ✅ Error states handled gracefully with retry capability
60
+ - ✅ Loading states provide good user experience
61
+ - ✅ Admin bundle contains no server dependencies
62
+ - ✅ All linting errors resolved
63
+ - ✅ Build and bundle validation passes
64
+ - ✅ TypeScript types are properly exported and available
65
+
1
66
  ## [0.20.3] - 2025-07-31
2
67
 
3
68
  ### Fixed
@@ -0,0 +1,25 @@
1
+ import { UIFieldClientComponent } from 'payload';
2
+ import React from 'react';
3
+
4
+ declare const BroadcastInlinePreview: UIFieldClientComponent;
5
+ interface BroadcastInlinePreviewProps {
6
+ data?: any;
7
+ field?: any;
8
+ path?: string;
9
+ schemaPath?: string;
10
+ }
11
+
12
+ interface StatusBadgeProps {
13
+ cellData?: string;
14
+ rowData?: any;
15
+ }
16
+ declare const StatusBadge: React.FC<StatusBadgeProps>;
17
+
18
+ interface EmailPreviewProps {
19
+ content?: any;
20
+ subject?: string;
21
+ preheader?: string;
22
+ }
23
+ declare const EmailPreview: React.FC<EmailPreviewProps>;
24
+
25
+ export { BroadcastInlinePreview, type BroadcastInlinePreviewProps, EmailPreview, type EmailPreviewProps, StatusBadge, type StatusBadgeProps };
package/dist/admin.js CHANGED
@@ -2,17 +2,98 @@
2
2
  "use client";
3
3
 
4
4
  // src/admin/components/BroadcastInlinePreview.tsx
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- var BroadcastInlinePreview = ({
7
- field: _field,
8
- data: _data,
9
- ..._props
10
- }) => {
11
- return /* @__PURE__ */ jsx("div", { className: "broadcast-preview", children: /* @__PURE__ */ jsxs("div", { style: { padding: "1rem", border: "1px solid #e0e0e0", borderRadius: "4px" }, children: [
12
- /* @__PURE__ */ jsx("h3", { children: "Email Preview" }),
13
- /* @__PURE__ */ jsx("p", { children: "This is a simplified preview component for the admin bundle." }),
14
- /* @__PURE__ */ jsx("p", { children: "Full preview functionality will be available in the complete admin interface." })
15
- ] }) });
5
+ import { useState, useCallback } from "react";
6
+ import { useFormFields } from "@payloadcms/ui";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ var BroadcastInlinePreview = () => {
9
+ const [preview, setPreview] = useState("");
10
+ const [loading, setLoading] = useState(false);
11
+ const [showPreview, setShowPreview] = useState(false);
12
+ const [error, setError] = useState(null);
13
+ const fields = useFormFields(([fields2]) => fields2);
14
+ const generatePreview = useCallback(async () => {
15
+ try {
16
+ setLoading(true);
17
+ setError(null);
18
+ const contentSection = fields?.contentSection;
19
+ const contentValue = contentSection?.content?.value;
20
+ if (!contentValue) {
21
+ setError("No content available to preview");
22
+ setLoading(false);
23
+ return;
24
+ }
25
+ const response = await fetch("/api/broadcasts/preview", {
26
+ method: "POST",
27
+ headers: { "Content-Type": "application/json" },
28
+ body: JSON.stringify({ content: contentValue })
29
+ });
30
+ if (!response.ok) {
31
+ throw new Error(`Preview failed: ${response.statusText}`);
32
+ }
33
+ const data = await response.json();
34
+ setPreview(data.html || "");
35
+ setShowPreview(true);
36
+ } catch (err) {
37
+ console.error("Preview generation error:", err);
38
+ setError(err instanceof Error ? err.message : "Failed to generate preview");
39
+ } finally {
40
+ setLoading(false);
41
+ }
42
+ }, [fields]);
43
+ return /* @__PURE__ */ jsxs("div", { className: "field-type", children: [
44
+ /* @__PURE__ */ jsx("div", { className: "field-label", children: "Email Preview" }),
45
+ !showPreview ? /* @__PURE__ */ jsxs("div", { className: "preview-controls", children: [
46
+ /* @__PURE__ */ jsx(
47
+ "button",
48
+ {
49
+ type: "button",
50
+ onClick: generatePreview,
51
+ disabled: loading,
52
+ className: "btn btn--style-primary btn--icon-style-without-border btn--size-small",
53
+ style: { marginBottom: "1rem" },
54
+ children: loading ? "Generating Preview..." : "Generate Preview"
55
+ }
56
+ ),
57
+ error && /* @__PURE__ */ jsx("div", { className: "error-message", style: { color: "#dc2626", marginTop: "0.5rem" }, children: error })
58
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
59
+ /* @__PURE__ */ jsxs("div", { className: "preview-controls", style: { marginBottom: "1rem" }, children: [
60
+ /* @__PURE__ */ jsx(
61
+ "button",
62
+ {
63
+ type: "button",
64
+ onClick: () => setShowPreview(false),
65
+ className: "btn btn--style-secondary btn--icon-style-without-border btn--size-small",
66
+ style: { marginRight: "0.5rem" },
67
+ children: "Hide Preview"
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx(
71
+ "button",
72
+ {
73
+ type: "button",
74
+ onClick: generatePreview,
75
+ disabled: loading,
76
+ className: "btn btn--style-primary btn--icon-style-without-border btn--size-small",
77
+ children: loading ? "Regenerating..." : "Refresh Preview"
78
+ }
79
+ )
80
+ ] }),
81
+ /* @__PURE__ */ jsx("div", { className: "email-preview-container", children: /* @__PURE__ */ jsx(
82
+ "iframe",
83
+ {
84
+ srcDoc: preview,
85
+ style: {
86
+ width: "100%",
87
+ height: "600px",
88
+ border: "1px solid #e5e7eb",
89
+ borderRadius: "0.375rem",
90
+ backgroundColor: "white"
91
+ },
92
+ title: "Email Preview"
93
+ }
94
+ ) })
95
+ ] })
96
+ ] });
16
97
  };
17
98
 
18
99
  // src/admin/components/StatusBadge.tsx
@@ -1887,6 +1887,7 @@ var createBroadcastPreviewEndpoint = (config, _collectionSlug) => {
1887
1887
  });
1888
1888
  return Response.json({
1889
1889
  success: true,
1890
+ html: htmlContent,
1890
1891
  preview: {
1891
1892
  subject: subject || "Preview",
1892
1893
  preheader: preheader || "",