payload-plugin-newsletter 0.15.0 → 0.15.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 +28 -0
- package/README.md +4 -2
- package/dist/collections.cjs +183 -11
- package/dist/collections.cjs.map +1 -1
- package/dist/collections.js +183 -11
- package/dist/collections.js.map +1 -1
- package/dist/fields.cjs +182 -6
- package/dist/fields.cjs.map +1 -1
- package/dist/fields.d.cts +16 -1
- package/dist/fields.d.ts +16 -1
- package/dist/fields.js +178 -5
- package/dist/fields.js.map +1 -1
- package/dist/index.cjs +183 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +183 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/fields.cjs
CHANGED
|
@@ -32,14 +32,114 @@ var fields_exports = {};
|
|
|
32
32
|
__export(fields_exports, {
|
|
33
33
|
createBroadcastInlinePreviewField: () => createBroadcastInlinePreviewField,
|
|
34
34
|
createEmailContentField: () => createEmailContentField,
|
|
35
|
+
createEmailLexicalEditor: () => createEmailLexicalEditor,
|
|
36
|
+
createEmailSafeBlocks: () => createEmailSafeBlocks,
|
|
35
37
|
createEmailSafeFeatures: () => createEmailSafeFeatures,
|
|
36
38
|
createNewsletterSchedulingFields: () => createNewsletterSchedulingFields,
|
|
37
|
-
emailSafeFeatures: () => emailSafeFeatures
|
|
39
|
+
emailSafeFeatures: () => emailSafeFeatures,
|
|
40
|
+
validateEmailBlocks: () => validateEmailBlocks
|
|
38
41
|
});
|
|
39
42
|
module.exports = __toCommonJS(fields_exports);
|
|
40
43
|
|
|
41
44
|
// src/fields/emailContent.ts
|
|
42
45
|
var import_richtext_lexical = require("@payloadcms/richtext-lexical");
|
|
46
|
+
|
|
47
|
+
// src/utils/blockValidation.ts
|
|
48
|
+
var EMAIL_INCOMPATIBLE_TYPES = [
|
|
49
|
+
"chart",
|
|
50
|
+
"dataTable",
|
|
51
|
+
"interactive",
|
|
52
|
+
"streamable",
|
|
53
|
+
"video",
|
|
54
|
+
"iframe",
|
|
55
|
+
"form",
|
|
56
|
+
"carousel",
|
|
57
|
+
"tabs",
|
|
58
|
+
"accordion",
|
|
59
|
+
"map"
|
|
60
|
+
];
|
|
61
|
+
var validateEmailBlocks = (blocks) => {
|
|
62
|
+
blocks.forEach((block) => {
|
|
63
|
+
if (EMAIL_INCOMPATIBLE_TYPES.includes(block.slug)) {
|
|
64
|
+
console.warn(`\u26A0\uFE0F Block "${block.slug}" may not be email-compatible. Consider creating an email-specific version.`);
|
|
65
|
+
}
|
|
66
|
+
const hasComplexFields = block.fields?.some((field) => {
|
|
67
|
+
const complexTypes = ["code", "json", "richText", "blocks", "array"];
|
|
68
|
+
return complexTypes.includes(field.type);
|
|
69
|
+
});
|
|
70
|
+
if (hasComplexFields) {
|
|
71
|
+
console.warn(`\u26A0\uFE0F Block "${block.slug}" contains complex field types that may not render consistently in email clients.`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
var createEmailSafeBlocks = (customBlocks = []) => {
|
|
76
|
+
validateEmailBlocks(customBlocks);
|
|
77
|
+
const baseBlocks = [
|
|
78
|
+
{
|
|
79
|
+
slug: "button",
|
|
80
|
+
fields: [
|
|
81
|
+
{
|
|
82
|
+
name: "text",
|
|
83
|
+
type: "text",
|
|
84
|
+
label: "Button Text",
|
|
85
|
+
required: true
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "url",
|
|
89
|
+
type: "text",
|
|
90
|
+
label: "Button URL",
|
|
91
|
+
required: true,
|
|
92
|
+
admin: {
|
|
93
|
+
description: "Enter the full URL (including https://)"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "style",
|
|
98
|
+
type: "select",
|
|
99
|
+
label: "Button Style",
|
|
100
|
+
defaultValue: "primary",
|
|
101
|
+
options: [
|
|
102
|
+
{ label: "Primary", value: "primary" },
|
|
103
|
+
{ label: "Secondary", value: "secondary" },
|
|
104
|
+
{ label: "Outline", value: "outline" }
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
],
|
|
108
|
+
interfaceName: "EmailButton",
|
|
109
|
+
labels: {
|
|
110
|
+
singular: "Button",
|
|
111
|
+
plural: "Buttons"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
slug: "divider",
|
|
116
|
+
fields: [
|
|
117
|
+
{
|
|
118
|
+
name: "style",
|
|
119
|
+
type: "select",
|
|
120
|
+
label: "Divider Style",
|
|
121
|
+
defaultValue: "solid",
|
|
122
|
+
options: [
|
|
123
|
+
{ label: "Solid", value: "solid" },
|
|
124
|
+
{ label: "Dashed", value: "dashed" },
|
|
125
|
+
{ label: "Dotted", value: "dotted" }
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
interfaceName: "EmailDivider",
|
|
130
|
+
labels: {
|
|
131
|
+
singular: "Divider",
|
|
132
|
+
plural: "Dividers"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
return [
|
|
137
|
+
...baseBlocks,
|
|
138
|
+
...customBlocks
|
|
139
|
+
];
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// src/fields/emailContent.ts
|
|
43
143
|
var createEmailSafeFeatures = (additionalBlocks) => {
|
|
44
144
|
const baseBlocks = [
|
|
45
145
|
{
|
|
@@ -177,16 +277,89 @@ var createEmailSafeFeatures = (additionalBlocks) => {
|
|
|
177
277
|
})
|
|
178
278
|
];
|
|
179
279
|
};
|
|
280
|
+
var createEmailLexicalEditor = (customBlocks = []) => {
|
|
281
|
+
const emailSafeBlocks = createEmailSafeBlocks(customBlocks);
|
|
282
|
+
return (0, import_richtext_lexical.lexicalEditor)({
|
|
283
|
+
features: [
|
|
284
|
+
// Toolbars
|
|
285
|
+
(0, import_richtext_lexical.FixedToolbarFeature)(),
|
|
286
|
+
(0, import_richtext_lexical.InlineToolbarFeature)(),
|
|
287
|
+
// Basic text formatting
|
|
288
|
+
(0, import_richtext_lexical.BoldFeature)(),
|
|
289
|
+
(0, import_richtext_lexical.ItalicFeature)(),
|
|
290
|
+
(0, import_richtext_lexical.UnderlineFeature)(),
|
|
291
|
+
(0, import_richtext_lexical.StrikethroughFeature)(),
|
|
292
|
+
// Links with enhanced configuration
|
|
293
|
+
(0, import_richtext_lexical.LinkFeature)({
|
|
294
|
+
fields: [
|
|
295
|
+
{
|
|
296
|
+
name: "url",
|
|
297
|
+
type: "text",
|
|
298
|
+
required: true,
|
|
299
|
+
admin: {
|
|
300
|
+
description: "Enter the full URL (including https://)"
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: "newTab",
|
|
305
|
+
type: "checkbox",
|
|
306
|
+
label: "Open in new tab",
|
|
307
|
+
defaultValue: false
|
|
308
|
+
}
|
|
309
|
+
]
|
|
310
|
+
}),
|
|
311
|
+
// Lists
|
|
312
|
+
(0, import_richtext_lexical.OrderedListFeature)(),
|
|
313
|
+
(0, import_richtext_lexical.UnorderedListFeature)(),
|
|
314
|
+
// Headings - limited to h1, h2, h3 for email compatibility
|
|
315
|
+
(0, import_richtext_lexical.HeadingFeature)({
|
|
316
|
+
enabledHeadingSizes: ["h1", "h2", "h3"]
|
|
317
|
+
}),
|
|
318
|
+
// Basic paragraph and alignment
|
|
319
|
+
(0, import_richtext_lexical.ParagraphFeature)(),
|
|
320
|
+
(0, import_richtext_lexical.AlignFeature)(),
|
|
321
|
+
// Blockquotes
|
|
322
|
+
(0, import_richtext_lexical.BlockquoteFeature)(),
|
|
323
|
+
// Upload feature for images
|
|
324
|
+
(0, import_richtext_lexical.UploadFeature)({
|
|
325
|
+
collections: {
|
|
326
|
+
media: {
|
|
327
|
+
fields: [
|
|
328
|
+
{
|
|
329
|
+
name: "caption",
|
|
330
|
+
type: "text",
|
|
331
|
+
admin: {
|
|
332
|
+
description: "Optional caption for the image"
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
name: "altText",
|
|
337
|
+
type: "text",
|
|
338
|
+
label: "Alt Text",
|
|
339
|
+
required: true,
|
|
340
|
+
admin: {
|
|
341
|
+
description: "Alternative text for accessibility and when image cannot be displayed"
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}),
|
|
348
|
+
// Email-safe blocks (processed server-side)
|
|
349
|
+
(0, import_richtext_lexical.BlocksFeature)({
|
|
350
|
+
blocks: emailSafeBlocks
|
|
351
|
+
})
|
|
352
|
+
]
|
|
353
|
+
});
|
|
354
|
+
};
|
|
180
355
|
var emailSafeFeatures = createEmailSafeFeatures();
|
|
181
356
|
var createEmailContentField = (overrides) => {
|
|
182
|
-
const
|
|
357
|
+
const editor = overrides?.editor || createEmailLexicalEditor(overrides?.additionalBlocks);
|
|
183
358
|
return {
|
|
184
359
|
name: "content",
|
|
185
360
|
type: "richText",
|
|
186
361
|
required: true,
|
|
187
|
-
editor
|
|
188
|
-
features
|
|
189
|
-
}),
|
|
362
|
+
editor,
|
|
190
363
|
admin: {
|
|
191
364
|
description: "Email content with limited formatting for compatibility",
|
|
192
365
|
...overrides?.admin
|
|
@@ -380,8 +553,11 @@ function createMarkdownFieldInternal(config) {
|
|
|
380
553
|
0 && (module.exports = {
|
|
381
554
|
createBroadcastInlinePreviewField,
|
|
382
555
|
createEmailContentField,
|
|
556
|
+
createEmailLexicalEditor,
|
|
557
|
+
createEmailSafeBlocks,
|
|
383
558
|
createEmailSafeFeatures,
|
|
384
559
|
createNewsletterSchedulingFields,
|
|
385
|
-
emailSafeFeatures
|
|
560
|
+
emailSafeFeatures,
|
|
561
|
+
validateEmailBlocks
|
|
386
562
|
});
|
|
387
563
|
//# sourceMappingURL=fields.cjs.map
|
package/dist/fields.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/exports/fields.ts","../src/fields/emailContent.ts","../src/fields/broadcastInlinePreview.ts","../src/fields/newsletterScheduling.ts"],"sourcesContent":["// Field configurations\nexport { createEmailContentField, emailSafeFeatures, createEmailSafeFeatures } from '../fields/emailContent'\nexport { createBroadcastInlinePreviewField } from '../fields/broadcastInlinePreview'\nexport { createNewsletterSchedulingFields } from '../fields/newsletterScheduling'","import { \n BoldFeature,\n ItalicFeature,\n UnderlineFeature,\n StrikethroughFeature,\n LinkFeature,\n OrderedListFeature,\n UnorderedListFeature,\n HeadingFeature,\n ParagraphFeature,\n AlignFeature,\n BlockquoteFeature,\n BlocksFeature,\n UploadFeature,\n FixedToolbarFeature,\n InlineToolbarFeature,\n lexicalEditor,\n} from '@payloadcms/richtext-lexical'\nimport type { RichTextField, Block } from 'payload'\n\n/**\n * Creates email-safe features for Lexical editor with optional additional blocks\n * Only includes features that render consistently across email clients\n */\n// Using any[] here because Payload's FeatureProviderServer type is complex\n// and varies between versions. The features are properly typed by Payload internally.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const createEmailSafeFeatures = (additionalBlocks?: Block[]): any[] => {\n // Base email-safe blocks\n const baseBlocks = [\n {\n slug: 'button',\n fields: [\n {\n name: 'text',\n type: 'text',\n label: 'Button Text',\n required: true,\n },\n {\n name: 'url',\n type: 'text',\n label: 'Button URL',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'style',\n type: 'select',\n label: 'Button Style',\n defaultValue: 'primary',\n options: [\n { label: 'Primary', value: 'primary' },\n { label: 'Secondary', value: 'secondary' },\n { label: 'Outline', value: 'outline' },\n ],\n },\n ],\n interfaceName: 'EmailButton',\n labels: {\n singular: 'Button',\n plural: 'Buttons',\n },\n },\n {\n slug: 'divider',\n fields: [\n {\n name: 'style',\n type: 'select',\n label: 'Divider Style',\n defaultValue: 'solid',\n options: [\n { label: 'Solid', value: 'solid' },\n { label: 'Dashed', value: 'dashed' },\n { label: 'Dotted', value: 'dotted' },\n ],\n },\n ],\n interfaceName: 'EmailDivider',\n labels: {\n singular: 'Divider',\n plural: 'Dividers',\n },\n },\n ] as Block[]\n\n // Merge additional blocks if provided\n const allBlocks = [\n ...baseBlocks,\n ...(additionalBlocks || [])\n ]\n\n return [\n // Toolbars\n FixedToolbarFeature(), // Fixed toolbar at the top\n InlineToolbarFeature(), // Floating toolbar when text is selected\n \n // Basic text formatting\n BoldFeature(),\n ItalicFeature(),\n UnderlineFeature(),\n StrikethroughFeature(),\n \n // Links with enhanced configuration\n LinkFeature({\n fields: [\n {\n name: 'url',\n type: 'text',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'newTab',\n type: 'checkbox',\n label: 'Open in new tab',\n defaultValue: false,\n },\n ],\n }),\n \n // Lists\n OrderedListFeature(),\n UnorderedListFeature(),\n \n // Headings - limited to h1, h2, h3 for email compatibility\n HeadingFeature({\n enabledHeadingSizes: ['h1', 'h2', 'h3'],\n }),\n \n // Basic paragraph and alignment\n ParagraphFeature(),\n AlignFeature(),\n \n // Blockquotes\n BlockquoteFeature(),\n \n // Upload feature for images\n UploadFeature({\n collections: {\n media: {\n fields: [\n {\n name: 'caption',\n type: 'text',\n admin: {\n description: 'Optional caption for the image',\n },\n },\n {\n name: 'altText',\n type: 'text',\n label: 'Alt Text',\n required: true,\n admin: {\n description: 'Alternative text for accessibility and when image cannot be displayed',\n },\n },\n ],\n },\n },\n }),\n \n // Custom blocks for email-specific content\n BlocksFeature({\n blocks: allBlocks,\n }),\n ]\n}\n\n/**\n * Legacy export for backward compatibility\n */\nexport const emailSafeFeatures = createEmailSafeFeatures()\n\n/**\n * Creates an email-safe rich text field configuration\n */\nexport const createEmailContentField = (\n overrides?: Partial<RichTextField> & {\n additionalBlocks?: Block[]\n }\n): RichTextField => {\n // Create features array with blocks\n const features = createEmailSafeFeatures(overrides?.additionalBlocks)\n\n return {\n name: 'content',\n type: 'richText',\n required: true,\n editor: lexicalEditor({\n features,\n }),\n admin: {\n description: 'Email content with limited formatting for compatibility',\n ...overrides?.admin,\n },\n ...overrides,\n }\n}","import type { Field } from 'payload'\n\nexport const createBroadcastInlinePreviewField = (): Field => {\n return {\n name: 'broadcastInlinePreview',\n type: 'ui',\n admin: {\n components: {\n Field: 'payload-plugin-newsletter/components#BroadcastInlinePreview',\n },\n },\n }\n}","import type { Field } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport function createNewsletterSchedulingFields(\n config: NewsletterPluginConfig\n): Field[] {\n const groupName = config.features?.newsletterScheduling?.fields?.groupName || 'newsletterScheduling'\n const contentField = config.features?.newsletterScheduling?.fields?.contentField || 'content'\n const createMarkdownField = config.features?.newsletterScheduling?.fields?.createMarkdownField !== false\n\n const fields: Field[] = [\n {\n name: groupName,\n type: 'group',\n label: 'Newsletter Scheduling',\n admin: {\n condition: (data, { user }) => user?.collection === 'users', // Only show for admin users\n },\n fields: [\n {\n name: 'scheduled',\n type: 'checkbox',\n label: 'Schedule for Newsletter',\n defaultValue: false,\n admin: {\n description: 'Schedule this content to be sent as a newsletter',\n },\n },\n {\n name: 'scheduledDate',\n type: 'date',\n label: 'Send Date',\n required: true,\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'When to send this newsletter',\n },\n },\n {\n name: 'sentDate',\n type: 'date',\n label: 'Sent Date',\n admin: {\n readOnly: true,\n condition: (data) => data?.[groupName]?.sendStatus === 'sent',\n description: 'When this newsletter was sent',\n },\n },\n {\n name: 'sendStatus',\n type: 'select',\n label: 'Status',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Sending', value: 'sending' },\n { label: 'Sent', value: 'sent' },\n { label: 'Failed', value: 'failed' },\n ],\n defaultValue: 'draft',\n admin: {\n readOnly: true,\n description: 'Current send status',\n },\n },\n {\n name: 'emailSubject',\n type: 'text',\n label: 'Email Subject',\n required: true,\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Subject line for the newsletter email',\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Email Preheader',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Preview text that appears after the subject line',\n },\n },\n {\n name: 'segments',\n type: 'select',\n label: 'Target Segments',\n hasMany: true,\n options: [\n { label: 'All Subscribers', value: 'all' },\n ...(config.i18n?.locales?.map(locale => ({\n label: `${locale.toUpperCase()} Subscribers`,\n value: locale,\n })) || []),\n ],\n defaultValue: ['all'],\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Which subscriber segments to send to',\n },\n },\n {\n name: 'testEmails',\n type: 'array',\n label: 'Test Email Recipients',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled && data?.[groupName]?.sendStatus === 'draft',\n description: 'Send test emails before scheduling',\n },\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n ],\n },\n ],\n },\n ]\n\n // Add markdown companion field if requested\n if (createMarkdownField) {\n fields.push(createMarkdownFieldInternal({\n name: `${contentField}Markdown`,\n richTextField: contentField,\n label: 'Email Content (Markdown)',\n admin: {\n position: 'sidebar',\n condition: (data: any) => Boolean(data?.[contentField] && data?.[groupName]?.scheduled),\n description: 'Markdown version for email rendering',\n readOnly: true,\n },\n }))\n }\n\n return fields\n}\n\n/**\n * Create a markdown companion field for rich text\n * This creates a virtual field that converts rich text to markdown\n */\nfunction createMarkdownFieldInternal(config: {\n name: string\n richTextField: string\n label?: string\n admin?: any\n}): Field {\n return {\n name: config.name,\n type: 'textarea',\n label: config.label || 'Markdown',\n admin: {\n ...config.admin,\n description: config.admin?.description || 'Auto-generated from rich text content',\n },\n hooks: {\n afterRead: [\n async ({ data }) => {\n // Convert rich text to markdown on read\n if (data?.[config.richTextField]) {\n try {\n const { convertLexicalToMarkdown } = await import('@payloadcms/richtext-lexical')\n return convertLexicalToMarkdown({\n data: data[config.richTextField],\n } as any)\n } catch {\n return ''\n }\n }\n return ''\n },\n ],\n beforeChange: [\n () => {\n // Don't save markdown to database\n return null\n },\n ],\n },\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/exports/fields.ts","../src/fields/emailContent.ts","../src/utils/blockValidation.ts","../src/fields/broadcastInlinePreview.ts","../src/fields/newsletterScheduling.ts"],"sourcesContent":["// Field configurations\nexport { createEmailContentField, emailSafeFeatures, createEmailSafeFeatures, createEmailLexicalEditor } from '../fields/emailContent'\nexport { createBroadcastInlinePreviewField } from '../fields/broadcastInlinePreview'\nexport { createNewsletterSchedulingFields } from '../fields/newsletterScheduling'\nexport { createEmailSafeBlocks, validateEmailBlocks } from '../utils/blockValidation'","import { \n BoldFeature,\n ItalicFeature,\n UnderlineFeature,\n StrikethroughFeature,\n LinkFeature,\n OrderedListFeature,\n UnorderedListFeature,\n HeadingFeature,\n ParagraphFeature,\n AlignFeature,\n BlockquoteFeature,\n BlocksFeature,\n UploadFeature,\n FixedToolbarFeature,\n InlineToolbarFeature,\n lexicalEditor,\n} from '@payloadcms/richtext-lexical'\nimport type { RichTextField, Block } from 'payload'\nimport { createEmailSafeBlocks } from '../utils/blockValidation'\n\n/**\n * Creates email-safe features for Lexical editor with optional additional blocks\n * Only includes features that render consistently across email clients\n */\n// Using any[] here because Payload's FeatureProviderServer type is complex\n// and varies between versions. The features are properly typed by Payload internally.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const createEmailSafeFeatures = (additionalBlocks?: Block[]): any[] => {\n // Base email-safe blocks\n const baseBlocks = [\n {\n slug: 'button',\n fields: [\n {\n name: 'text',\n type: 'text',\n label: 'Button Text',\n required: true,\n },\n {\n name: 'url',\n type: 'text',\n label: 'Button URL',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'style',\n type: 'select',\n label: 'Button Style',\n defaultValue: 'primary',\n options: [\n { label: 'Primary', value: 'primary' },\n { label: 'Secondary', value: 'secondary' },\n { label: 'Outline', value: 'outline' },\n ],\n },\n ],\n interfaceName: 'EmailButton',\n labels: {\n singular: 'Button',\n plural: 'Buttons',\n },\n },\n {\n slug: 'divider',\n fields: [\n {\n name: 'style',\n type: 'select',\n label: 'Divider Style',\n defaultValue: 'solid',\n options: [\n { label: 'Solid', value: 'solid' },\n { label: 'Dashed', value: 'dashed' },\n { label: 'Dotted', value: 'dotted' },\n ],\n },\n ],\n interfaceName: 'EmailDivider',\n labels: {\n singular: 'Divider',\n plural: 'Dividers',\n },\n },\n ] as Block[]\n\n // Merge additional blocks if provided\n const allBlocks = [\n ...baseBlocks,\n ...(additionalBlocks || [])\n ]\n\n return [\n // Toolbars\n FixedToolbarFeature(), // Fixed toolbar at the top\n InlineToolbarFeature(), // Floating toolbar when text is selected\n \n // Basic text formatting\n BoldFeature(),\n ItalicFeature(),\n UnderlineFeature(),\n StrikethroughFeature(),\n \n // Links with enhanced configuration\n LinkFeature({\n fields: [\n {\n name: 'url',\n type: 'text',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'newTab',\n type: 'checkbox',\n label: 'Open in new tab',\n defaultValue: false,\n },\n ],\n }),\n \n // Lists\n OrderedListFeature(),\n UnorderedListFeature(),\n \n // Headings - limited to h1, h2, h3 for email compatibility\n HeadingFeature({\n enabledHeadingSizes: ['h1', 'h2', 'h3'],\n }),\n \n // Basic paragraph and alignment\n ParagraphFeature(),\n AlignFeature(),\n \n // Blockquotes\n BlockquoteFeature(),\n \n // Upload feature for images\n UploadFeature({\n collections: {\n media: {\n fields: [\n {\n name: 'caption',\n type: 'text',\n admin: {\n description: 'Optional caption for the image',\n },\n },\n {\n name: 'altText',\n type: 'text',\n label: 'Alt Text',\n required: true,\n admin: {\n description: 'Alternative text for accessibility and when image cannot be displayed',\n },\n },\n ],\n },\n },\n }),\n \n // Custom blocks for email-specific content\n BlocksFeature({\n blocks: allBlocks,\n }),\n ]\n}\n\n/**\n * Creates a Lexical editor configured specifically for email content\n * Processes blocks server-side to avoid client serialization issues\n */\nexport const createEmailLexicalEditor = (customBlocks: Block[] = []): any => {\n const emailSafeBlocks = createEmailSafeBlocks(customBlocks)\n \n return lexicalEditor({\n features: [\n // Toolbars\n FixedToolbarFeature(),\n InlineToolbarFeature(),\n \n // Basic text formatting\n BoldFeature(),\n ItalicFeature(),\n UnderlineFeature(),\n StrikethroughFeature(),\n \n // Links with enhanced configuration\n LinkFeature({\n fields: [\n {\n name: 'url',\n type: 'text',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'newTab',\n type: 'checkbox',\n label: 'Open in new tab',\n defaultValue: false,\n },\n ],\n }),\n \n // Lists\n OrderedListFeature(),\n UnorderedListFeature(),\n \n // Headings - limited to h1, h2, h3 for email compatibility\n HeadingFeature({\n enabledHeadingSizes: ['h1', 'h2', 'h3'],\n }),\n \n // Basic paragraph and alignment\n ParagraphFeature(),\n AlignFeature(),\n \n // Blockquotes\n BlockquoteFeature(),\n \n // Upload feature for images\n UploadFeature({\n collections: {\n media: {\n fields: [\n {\n name: 'caption',\n type: 'text',\n admin: {\n description: 'Optional caption for the image',\n },\n },\n {\n name: 'altText',\n type: 'text',\n label: 'Alt Text',\n required: true,\n admin: {\n description: 'Alternative text for accessibility and when image cannot be displayed',\n },\n },\n ],\n },\n },\n }),\n \n // Email-safe blocks (processed server-side)\n BlocksFeature({\n blocks: emailSafeBlocks,\n }),\n ],\n })\n}\n\n/**\n * Legacy export for backward compatibility\n */\nexport const emailSafeFeatures = createEmailSafeFeatures()\n\n/**\n * Creates an email-safe rich text field configuration\n */\nexport const createEmailContentField = (\n overrides?: Partial<RichTextField> & {\n additionalBlocks?: Block[]\n editor?: any // Lexical editor instance\n }\n): RichTextField => {\n // Use provided editor or create one with blocks\n const editor = overrides?.editor || createEmailLexicalEditor(overrides?.additionalBlocks)\n\n return {\n name: 'content',\n type: 'richText',\n required: true,\n editor,\n admin: {\n description: 'Email content with limited formatting for compatibility',\n ...overrides?.admin,\n },\n ...overrides,\n }\n}","import type { Block } from 'payload'\n\n/**\n * Email-incompatible block types that should be warned about\n */\nconst EMAIL_INCOMPATIBLE_TYPES = [\n 'chart',\n 'dataTable', \n 'interactive',\n 'streamable',\n 'video',\n 'iframe',\n 'form',\n 'carousel',\n 'tabs',\n 'accordion',\n 'map'\n]\n\n/**\n * Validates that blocks are email-compatible and warns about potential issues\n */\nexport const validateEmailBlocks = (blocks: Block[]): void => {\n blocks.forEach(block => {\n if (EMAIL_INCOMPATIBLE_TYPES.includes(block.slug)) {\n console.warn(`⚠️ Block \"${block.slug}\" may not be email-compatible. Consider creating an email-specific version.`)\n }\n \n // Check for complex field types that might not work in emails\n const hasComplexFields = block.fields?.some(field => {\n const complexTypes = ['code', 'json', 'richText', 'blocks', 'array']\n return complexTypes.includes(field.type)\n })\n \n if (hasComplexFields) {\n console.warn(`⚠️ Block \"${block.slug}\" contains complex field types that may not render consistently in email clients.`)\n }\n })\n}\n\n/**\n * Creates email-safe block configurations by filtering and validating blocks\n */\nexport const createEmailSafeBlocks = (customBlocks: Block[] = []): Block[] => {\n // Validate blocks\n validateEmailBlocks(customBlocks)\n \n // Base email-safe blocks that come with the plugin\n const baseBlocks: Block[] = [\n {\n slug: 'button',\n fields: [\n {\n name: 'text',\n type: 'text',\n label: 'Button Text',\n required: true,\n },\n {\n name: 'url',\n type: 'text',\n label: 'Button URL',\n required: true,\n admin: {\n description: 'Enter the full URL (including https://)',\n },\n },\n {\n name: 'style',\n type: 'select',\n label: 'Button Style',\n defaultValue: 'primary',\n options: [\n { label: 'Primary', value: 'primary' },\n { label: 'Secondary', value: 'secondary' },\n { label: 'Outline', value: 'outline' },\n ],\n },\n ],\n interfaceName: 'EmailButton',\n labels: {\n singular: 'Button',\n plural: 'Buttons',\n },\n },\n {\n slug: 'divider',\n fields: [\n {\n name: 'style',\n type: 'select',\n label: 'Divider Style',\n defaultValue: 'solid',\n options: [\n { label: 'Solid', value: 'solid' },\n { label: 'Dashed', value: 'dashed' },\n { label: 'Dotted', value: 'dotted' },\n ],\n },\n ],\n interfaceName: 'EmailDivider',\n labels: {\n singular: 'Divider',\n plural: 'Dividers',\n },\n },\n ]\n \n // Combine base blocks with custom blocks\n return [\n ...baseBlocks,\n ...customBlocks\n ]\n}","import type { Field } from 'payload'\n\nexport const createBroadcastInlinePreviewField = (): Field => {\n return {\n name: 'broadcastInlinePreview',\n type: 'ui',\n admin: {\n components: {\n Field: 'payload-plugin-newsletter/components#BroadcastInlinePreview',\n },\n },\n }\n}","import type { Field } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport function createNewsletterSchedulingFields(\n config: NewsletterPluginConfig\n): Field[] {\n const groupName = config.features?.newsletterScheduling?.fields?.groupName || 'newsletterScheduling'\n const contentField = config.features?.newsletterScheduling?.fields?.contentField || 'content'\n const createMarkdownField = config.features?.newsletterScheduling?.fields?.createMarkdownField !== false\n\n const fields: Field[] = [\n {\n name: groupName,\n type: 'group',\n label: 'Newsletter Scheduling',\n admin: {\n condition: (data, { user }) => user?.collection === 'users', // Only show for admin users\n },\n fields: [\n {\n name: 'scheduled',\n type: 'checkbox',\n label: 'Schedule for Newsletter',\n defaultValue: false,\n admin: {\n description: 'Schedule this content to be sent as a newsletter',\n },\n },\n {\n name: 'scheduledDate',\n type: 'date',\n label: 'Send Date',\n required: true,\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'When to send this newsletter',\n },\n },\n {\n name: 'sentDate',\n type: 'date',\n label: 'Sent Date',\n admin: {\n readOnly: true,\n condition: (data) => data?.[groupName]?.sendStatus === 'sent',\n description: 'When this newsletter was sent',\n },\n },\n {\n name: 'sendStatus',\n type: 'select',\n label: 'Status',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Sending', value: 'sending' },\n { label: 'Sent', value: 'sent' },\n { label: 'Failed', value: 'failed' },\n ],\n defaultValue: 'draft',\n admin: {\n readOnly: true,\n description: 'Current send status',\n },\n },\n {\n name: 'emailSubject',\n type: 'text',\n label: 'Email Subject',\n required: true,\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Subject line for the newsletter email',\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Email Preheader',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Preview text that appears after the subject line',\n },\n },\n {\n name: 'segments',\n type: 'select',\n label: 'Target Segments',\n hasMany: true,\n options: [\n { label: 'All Subscribers', value: 'all' },\n ...(config.i18n?.locales?.map(locale => ({\n label: `${locale.toUpperCase()} Subscribers`,\n value: locale,\n })) || []),\n ],\n defaultValue: ['all'],\n admin: {\n condition: (data) => data?.[groupName]?.scheduled,\n description: 'Which subscriber segments to send to',\n },\n },\n {\n name: 'testEmails',\n type: 'array',\n label: 'Test Email Recipients',\n admin: {\n condition: (data) => data?.[groupName]?.scheduled && data?.[groupName]?.sendStatus === 'draft',\n description: 'Send test emails before scheduling',\n },\n fields: [\n {\n name: 'email',\n type: 'email',\n required: true,\n },\n ],\n },\n ],\n },\n ]\n\n // Add markdown companion field if requested\n if (createMarkdownField) {\n fields.push(createMarkdownFieldInternal({\n name: `${contentField}Markdown`,\n richTextField: contentField,\n label: 'Email Content (Markdown)',\n admin: {\n position: 'sidebar',\n condition: (data: any) => Boolean(data?.[contentField] && data?.[groupName]?.scheduled),\n description: 'Markdown version for email rendering',\n readOnly: true,\n },\n }))\n }\n\n return fields\n}\n\n/**\n * Create a markdown companion field for rich text\n * This creates a virtual field that converts rich text to markdown\n */\nfunction createMarkdownFieldInternal(config: {\n name: string\n richTextField: string\n label?: string\n admin?: any\n}): Field {\n return {\n name: config.name,\n type: 'textarea',\n label: config.label || 'Markdown',\n admin: {\n ...config.admin,\n description: config.admin?.description || 'Auto-generated from rich text content',\n },\n hooks: {\n afterRead: [\n async ({ data }) => {\n // Convert rich text to markdown on read\n if (data?.[config.richTextField]) {\n try {\n const { convertLexicalToMarkdown } = await import('@payloadcms/richtext-lexical')\n return convertLexicalToMarkdown({\n data: data[config.richTextField],\n } as any)\n } catch {\n return ''\n }\n }\n return ''\n },\n ],\n beforeChange: [\n () => {\n // Don't save markdown to database\n return null\n },\n ],\n },\n }\n}"],"mappings":"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","names":[]}
|
package/dist/fields.d.cts
CHANGED
|
@@ -6,6 +6,11 @@ import { NewsletterPluginConfig } from './types.cjs';
|
|
|
6
6
|
* Only includes features that render consistently across email clients
|
|
7
7
|
*/
|
|
8
8
|
declare const createEmailSafeFeatures: (additionalBlocks?: Block[]) => any[];
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Lexical editor configured specifically for email content
|
|
11
|
+
* Processes blocks server-side to avoid client serialization issues
|
|
12
|
+
*/
|
|
13
|
+
declare const createEmailLexicalEditor: (customBlocks?: Block[]) => any;
|
|
9
14
|
/**
|
|
10
15
|
* Legacy export for backward compatibility
|
|
11
16
|
*/
|
|
@@ -15,10 +20,20 @@ declare const emailSafeFeatures: any[];
|
|
|
15
20
|
*/
|
|
16
21
|
declare const createEmailContentField: (overrides?: Partial<RichTextField> & {
|
|
17
22
|
additionalBlocks?: Block[];
|
|
23
|
+
editor?: any;
|
|
18
24
|
}) => RichTextField;
|
|
19
25
|
|
|
20
26
|
declare const createBroadcastInlinePreviewField: () => Field;
|
|
21
27
|
|
|
22
28
|
declare function createNewsletterSchedulingFields(config: NewsletterPluginConfig): Field[];
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Validates that blocks are email-compatible and warns about potential issues
|
|
32
|
+
*/
|
|
33
|
+
declare const validateEmailBlocks: (blocks: Block[]) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Creates email-safe block configurations by filtering and validating blocks
|
|
36
|
+
*/
|
|
37
|
+
declare const createEmailSafeBlocks: (customBlocks?: Block[]) => Block[];
|
|
38
|
+
|
|
39
|
+
export { createBroadcastInlinePreviewField, createEmailContentField, createEmailLexicalEditor, createEmailSafeBlocks, createEmailSafeFeatures, createNewsletterSchedulingFields, emailSafeFeatures, validateEmailBlocks };
|
package/dist/fields.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { NewsletterPluginConfig } from './types.js';
|
|
|
6
6
|
* Only includes features that render consistently across email clients
|
|
7
7
|
*/
|
|
8
8
|
declare const createEmailSafeFeatures: (additionalBlocks?: Block[]) => any[];
|
|
9
|
+
/**
|
|
10
|
+
* Creates a Lexical editor configured specifically for email content
|
|
11
|
+
* Processes blocks server-side to avoid client serialization issues
|
|
12
|
+
*/
|
|
13
|
+
declare const createEmailLexicalEditor: (customBlocks?: Block[]) => any;
|
|
9
14
|
/**
|
|
10
15
|
* Legacy export for backward compatibility
|
|
11
16
|
*/
|
|
@@ -15,10 +20,20 @@ declare const emailSafeFeatures: any[];
|
|
|
15
20
|
*/
|
|
16
21
|
declare const createEmailContentField: (overrides?: Partial<RichTextField> & {
|
|
17
22
|
additionalBlocks?: Block[];
|
|
23
|
+
editor?: any;
|
|
18
24
|
}) => RichTextField;
|
|
19
25
|
|
|
20
26
|
declare const createBroadcastInlinePreviewField: () => Field;
|
|
21
27
|
|
|
22
28
|
declare function createNewsletterSchedulingFields(config: NewsletterPluginConfig): Field[];
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Validates that blocks are email-compatible and warns about potential issues
|
|
32
|
+
*/
|
|
33
|
+
declare const validateEmailBlocks: (blocks: Block[]) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Creates email-safe block configurations by filtering and validating blocks
|
|
36
|
+
*/
|
|
37
|
+
declare const createEmailSafeBlocks: (customBlocks?: Block[]) => Block[];
|
|
38
|
+
|
|
39
|
+
export { createBroadcastInlinePreviewField, createEmailContentField, createEmailLexicalEditor, createEmailSafeBlocks, createEmailSafeFeatures, createNewsletterSchedulingFields, emailSafeFeatures, validateEmailBlocks };
|
package/dist/fields.js
CHANGED
|
@@ -17,6 +17,103 @@ import {
|
|
|
17
17
|
InlineToolbarFeature,
|
|
18
18
|
lexicalEditor
|
|
19
19
|
} from "@payloadcms/richtext-lexical";
|
|
20
|
+
|
|
21
|
+
// src/utils/blockValidation.ts
|
|
22
|
+
var EMAIL_INCOMPATIBLE_TYPES = [
|
|
23
|
+
"chart",
|
|
24
|
+
"dataTable",
|
|
25
|
+
"interactive",
|
|
26
|
+
"streamable",
|
|
27
|
+
"video",
|
|
28
|
+
"iframe",
|
|
29
|
+
"form",
|
|
30
|
+
"carousel",
|
|
31
|
+
"tabs",
|
|
32
|
+
"accordion",
|
|
33
|
+
"map"
|
|
34
|
+
];
|
|
35
|
+
var validateEmailBlocks = (blocks) => {
|
|
36
|
+
blocks.forEach((block) => {
|
|
37
|
+
if (EMAIL_INCOMPATIBLE_TYPES.includes(block.slug)) {
|
|
38
|
+
console.warn(`\u26A0\uFE0F Block "${block.slug}" may not be email-compatible. Consider creating an email-specific version.`);
|
|
39
|
+
}
|
|
40
|
+
const hasComplexFields = block.fields?.some((field) => {
|
|
41
|
+
const complexTypes = ["code", "json", "richText", "blocks", "array"];
|
|
42
|
+
return complexTypes.includes(field.type);
|
|
43
|
+
});
|
|
44
|
+
if (hasComplexFields) {
|
|
45
|
+
console.warn(`\u26A0\uFE0F Block "${block.slug}" contains complex field types that may not render consistently in email clients.`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
var createEmailSafeBlocks = (customBlocks = []) => {
|
|
50
|
+
validateEmailBlocks(customBlocks);
|
|
51
|
+
const baseBlocks = [
|
|
52
|
+
{
|
|
53
|
+
slug: "button",
|
|
54
|
+
fields: [
|
|
55
|
+
{
|
|
56
|
+
name: "text",
|
|
57
|
+
type: "text",
|
|
58
|
+
label: "Button Text",
|
|
59
|
+
required: true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "url",
|
|
63
|
+
type: "text",
|
|
64
|
+
label: "Button URL",
|
|
65
|
+
required: true,
|
|
66
|
+
admin: {
|
|
67
|
+
description: "Enter the full URL (including https://)"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "style",
|
|
72
|
+
type: "select",
|
|
73
|
+
label: "Button Style",
|
|
74
|
+
defaultValue: "primary",
|
|
75
|
+
options: [
|
|
76
|
+
{ label: "Primary", value: "primary" },
|
|
77
|
+
{ label: "Secondary", value: "secondary" },
|
|
78
|
+
{ label: "Outline", value: "outline" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
interfaceName: "EmailButton",
|
|
83
|
+
labels: {
|
|
84
|
+
singular: "Button",
|
|
85
|
+
plural: "Buttons"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
slug: "divider",
|
|
90
|
+
fields: [
|
|
91
|
+
{
|
|
92
|
+
name: "style",
|
|
93
|
+
type: "select",
|
|
94
|
+
label: "Divider Style",
|
|
95
|
+
defaultValue: "solid",
|
|
96
|
+
options: [
|
|
97
|
+
{ label: "Solid", value: "solid" },
|
|
98
|
+
{ label: "Dashed", value: "dashed" },
|
|
99
|
+
{ label: "Dotted", value: "dotted" }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
interfaceName: "EmailDivider",
|
|
104
|
+
labels: {
|
|
105
|
+
singular: "Divider",
|
|
106
|
+
plural: "Dividers"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
return [
|
|
111
|
+
...baseBlocks,
|
|
112
|
+
...customBlocks
|
|
113
|
+
];
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// src/fields/emailContent.ts
|
|
20
117
|
var createEmailSafeFeatures = (additionalBlocks) => {
|
|
21
118
|
const baseBlocks = [
|
|
22
119
|
{
|
|
@@ -154,16 +251,89 @@ var createEmailSafeFeatures = (additionalBlocks) => {
|
|
|
154
251
|
})
|
|
155
252
|
];
|
|
156
253
|
};
|
|
254
|
+
var createEmailLexicalEditor = (customBlocks = []) => {
|
|
255
|
+
const emailSafeBlocks = createEmailSafeBlocks(customBlocks);
|
|
256
|
+
return lexicalEditor({
|
|
257
|
+
features: [
|
|
258
|
+
// Toolbars
|
|
259
|
+
FixedToolbarFeature(),
|
|
260
|
+
InlineToolbarFeature(),
|
|
261
|
+
// Basic text formatting
|
|
262
|
+
BoldFeature(),
|
|
263
|
+
ItalicFeature(),
|
|
264
|
+
UnderlineFeature(),
|
|
265
|
+
StrikethroughFeature(),
|
|
266
|
+
// Links with enhanced configuration
|
|
267
|
+
LinkFeature({
|
|
268
|
+
fields: [
|
|
269
|
+
{
|
|
270
|
+
name: "url",
|
|
271
|
+
type: "text",
|
|
272
|
+
required: true,
|
|
273
|
+
admin: {
|
|
274
|
+
description: "Enter the full URL (including https://)"
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: "newTab",
|
|
279
|
+
type: "checkbox",
|
|
280
|
+
label: "Open in new tab",
|
|
281
|
+
defaultValue: false
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
}),
|
|
285
|
+
// Lists
|
|
286
|
+
OrderedListFeature(),
|
|
287
|
+
UnorderedListFeature(),
|
|
288
|
+
// Headings - limited to h1, h2, h3 for email compatibility
|
|
289
|
+
HeadingFeature({
|
|
290
|
+
enabledHeadingSizes: ["h1", "h2", "h3"]
|
|
291
|
+
}),
|
|
292
|
+
// Basic paragraph and alignment
|
|
293
|
+
ParagraphFeature(),
|
|
294
|
+
AlignFeature(),
|
|
295
|
+
// Blockquotes
|
|
296
|
+
BlockquoteFeature(),
|
|
297
|
+
// Upload feature for images
|
|
298
|
+
UploadFeature({
|
|
299
|
+
collections: {
|
|
300
|
+
media: {
|
|
301
|
+
fields: [
|
|
302
|
+
{
|
|
303
|
+
name: "caption",
|
|
304
|
+
type: "text",
|
|
305
|
+
admin: {
|
|
306
|
+
description: "Optional caption for the image"
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
name: "altText",
|
|
311
|
+
type: "text",
|
|
312
|
+
label: "Alt Text",
|
|
313
|
+
required: true,
|
|
314
|
+
admin: {
|
|
315
|
+
description: "Alternative text for accessibility and when image cannot be displayed"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}),
|
|
322
|
+
// Email-safe blocks (processed server-side)
|
|
323
|
+
BlocksFeature({
|
|
324
|
+
blocks: emailSafeBlocks
|
|
325
|
+
})
|
|
326
|
+
]
|
|
327
|
+
});
|
|
328
|
+
};
|
|
157
329
|
var emailSafeFeatures = createEmailSafeFeatures();
|
|
158
330
|
var createEmailContentField = (overrides) => {
|
|
159
|
-
const
|
|
331
|
+
const editor = overrides?.editor || createEmailLexicalEditor(overrides?.additionalBlocks);
|
|
160
332
|
return {
|
|
161
333
|
name: "content",
|
|
162
334
|
type: "richText",
|
|
163
335
|
required: true,
|
|
164
|
-
editor
|
|
165
|
-
features
|
|
166
|
-
}),
|
|
336
|
+
editor,
|
|
167
337
|
admin: {
|
|
168
338
|
description: "Email content with limited formatting for compatibility",
|
|
169
339
|
...overrides?.admin
|
|
@@ -356,8 +526,11 @@ function createMarkdownFieldInternal(config) {
|
|
|
356
526
|
export {
|
|
357
527
|
createBroadcastInlinePreviewField,
|
|
358
528
|
createEmailContentField,
|
|
529
|
+
createEmailLexicalEditor,
|
|
530
|
+
createEmailSafeBlocks,
|
|
359
531
|
createEmailSafeFeatures,
|
|
360
532
|
createNewsletterSchedulingFields,
|
|
361
|
-
emailSafeFeatures
|
|
533
|
+
emailSafeFeatures,
|
|
534
|
+
validateEmailBlocks
|
|
362
535
|
};
|
|
363
536
|
//# sourceMappingURL=fields.js.map
|