@standhigher/react-email-editor 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/README.md +96 -182
- package/README.zh-CN.md +96 -182
- package/dist/index.d.ts +325 -104
- package/dist/index.js +4730 -3310
- package/dist/styles.css +858 -394
- package/docs/custom-blocks.md +491 -0
- package/docs/custom-blocks.zh-CN.md +490 -0
- package/package.json +23 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
2
|
+
import { ReactNode, ComponentType, InputHTMLAttributes, ButtonHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
declare const TEXT_ALIGNS: {
|
|
5
5
|
readonly left: "left";
|
|
@@ -32,44 +32,35 @@ declare const LINK_DECORATIONS: {
|
|
|
32
32
|
};
|
|
33
33
|
type LinkDecoration = (typeof LINK_DECORATIONS)[keyof typeof LINK_DECORATIONS];
|
|
34
34
|
|
|
35
|
-
declare const DOCUMENT_VERSION:
|
|
36
|
-
declare const FONT_FAMILIES: readonly
|
|
37
|
-
declare const
|
|
35
|
+
declare const DOCUMENT_VERSION: 4;
|
|
36
|
+
declare const FONT_FAMILIES: readonly ControlOption[];
|
|
37
|
+
declare const DEFAULT_EMAIL_BODY: EmailBodySettings;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
/** 邮件主体布局、外观和可继承的基础文字与链接样式。 */
|
|
40
|
+
interface EmailBodySettings {
|
|
40
41
|
textColor: string;
|
|
41
|
-
textAlign: TextAlign;
|
|
42
42
|
backgroundColor: string;
|
|
43
43
|
contentWidth: number;
|
|
44
|
-
contentAlign: HorizontalAlign;
|
|
45
44
|
fontFamily: string;
|
|
46
45
|
fontWeight: FontWeight;
|
|
47
|
-
contentBackgroundColor: string;
|
|
48
|
-
contentPadding: string;
|
|
49
|
-
outerPadding: string;
|
|
50
|
-
blockGap: string;
|
|
51
|
-
defaultFontSize: string;
|
|
52
|
-
defaultLineHeight: string;
|
|
53
|
-
paragraphSpacing: string;
|
|
54
|
-
listSpacing: string;
|
|
55
|
-
listIndent: string;
|
|
56
46
|
linkColor: string;
|
|
57
47
|
linkDecoration: LinkDecoration;
|
|
48
|
+
contentPadding: string;
|
|
49
|
+
blockGap: string;
|
|
58
50
|
borderWidth: string;
|
|
59
51
|
borderStyle: BorderStyle;
|
|
60
52
|
borderColor: string;
|
|
61
|
-
borderRadius: string;
|
|
62
53
|
}
|
|
63
54
|
interface EmailDocument {
|
|
64
55
|
version: typeof DOCUMENT_VERSION;
|
|
65
56
|
subject?: string;
|
|
66
|
-
|
|
57
|
+
body: EmailBodySettings;
|
|
67
58
|
blocks: EmailBlockNode[];
|
|
68
59
|
}
|
|
69
60
|
interface EmailBlockNode {
|
|
70
61
|
id: string;
|
|
71
62
|
type: string;
|
|
72
|
-
|
|
63
|
+
controls: Record<string, unknown>;
|
|
73
64
|
style?: EmailBlockStyle;
|
|
74
65
|
defaultData?: Record<string, unknown>;
|
|
75
66
|
}
|
|
@@ -94,7 +85,7 @@ interface EmailTypographyStyle {
|
|
|
94
85
|
linkDecoration?: LinkDecoration;
|
|
95
86
|
}
|
|
96
87
|
/** 按钮、图片和分割线自身的样式,与区块容器样式独立。 */
|
|
97
|
-
interface EmailElementStyle extends EmailDecorationStyle
|
|
88
|
+
interface EmailElementStyle extends EmailDecorationStyle {
|
|
98
89
|
padding?: string;
|
|
99
90
|
width?: string;
|
|
100
91
|
height?: string;
|
|
@@ -103,42 +94,33 @@ interface EmailElementStyle extends EmailDecorationStyle, EmailTypographyStyle {
|
|
|
103
94
|
interface EmailSpacingStyle {
|
|
104
95
|
padding?: string;
|
|
105
96
|
margin?: string;
|
|
106
|
-
/**
|
|
97
|
+
/** 自定义区块可通过 styleControls 启用;内置区块不支持。只使用 px。 */
|
|
107
98
|
height?: string;
|
|
108
99
|
}
|
|
109
100
|
interface EmailBlockStyle {
|
|
110
101
|
dimension?: EmailSpacingStyle;
|
|
102
|
+
/** 自定义区块可显式启用;内置区块的文字格式存于 controls.html。 */
|
|
111
103
|
typography?: EmailTypographyStyle;
|
|
112
104
|
decorations?: EmailDecorationStyle;
|
|
113
105
|
element?: EmailElementStyle;
|
|
114
106
|
}
|
|
115
107
|
|
|
116
|
-
|
|
117
|
-
interface FieldOption {
|
|
108
|
+
interface ControlOption {
|
|
118
109
|
label: string;
|
|
119
110
|
value: string;
|
|
120
111
|
}
|
|
121
|
-
interface
|
|
122
|
-
type: FieldType;
|
|
112
|
+
interface ControlConfig extends ControlDefinition {
|
|
123
113
|
name: string;
|
|
124
|
-
label: string;
|
|
125
|
-
defaultValue?: unknown;
|
|
126
|
-
placeholder?: string;
|
|
127
|
-
options?: FieldOption[];
|
|
128
|
-
rows?: number;
|
|
129
|
-
min?: number;
|
|
130
|
-
max?: number;
|
|
131
|
-
step?: number;
|
|
132
114
|
}
|
|
133
115
|
type StyleGroup = "general" | "dimension" | "typography" | "decorations";
|
|
134
116
|
type StyleControlType = "text" | "color" | "alignment" | "select" | "number" | "range" | "spacing" | "corners";
|
|
135
|
-
interface
|
|
117
|
+
interface StyleControlConfig {
|
|
136
118
|
/** e.g. "typography.fontSize" — which style slot this reads and writes */
|
|
137
119
|
id: string;
|
|
138
120
|
group: StyleGroup;
|
|
139
121
|
label: string;
|
|
140
122
|
control: StyleControlType;
|
|
141
|
-
options?:
|
|
123
|
+
options?: ControlOption[];
|
|
142
124
|
/** Unit suffix for a single-unit slider, e.g. "px". Omit for unitless values. */
|
|
143
125
|
unit?: string;
|
|
144
126
|
/** Email-safe units. A select appears only when more than one is listed. */
|
|
@@ -152,28 +134,40 @@ interface StyleFieldConfig {
|
|
|
152
134
|
type RenderMode = "canvas" | "email";
|
|
153
135
|
interface BlockRenderContext {
|
|
154
136
|
block: EmailBlockNode;
|
|
155
|
-
|
|
137
|
+
controls: Record<string, unknown>;
|
|
156
138
|
style: EmailBlockStyle;
|
|
157
139
|
/** canvas/email identify the consumer; HTML template resolution is applied by the shared renderer. */
|
|
158
140
|
mode: RenderMode;
|
|
159
|
-
|
|
141
|
+
body: EmailBodySettings;
|
|
142
|
+
}
|
|
143
|
+
type RichTextProfile = "text" | "heading" | "button";
|
|
144
|
+
/** 显式控制检查器的分组及字段归属,分组按声明顺序展示。 */
|
|
145
|
+
interface BlockInspectorSection {
|
|
146
|
+
title: string;
|
|
147
|
+
controlNames?: string[];
|
|
148
|
+
styleIds?: string[];
|
|
149
|
+
advancedStyleIds?: string[];
|
|
160
150
|
}
|
|
161
151
|
interface BlockDefinition {
|
|
162
152
|
type: string;
|
|
163
153
|
title: string;
|
|
164
154
|
icon?: ReactNode | string;
|
|
165
155
|
description?: string;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
156
|
+
controls?: ControlConfig[];
|
|
157
|
+
styleControls?: StyleControlConfig[];
|
|
158
|
+
inspectorSections?: BlockInspectorSection[];
|
|
159
|
+
readControls: (value: Record<string, unknown>) => Record<string, unknown>;
|
|
160
|
+
override?: boolean;
|
|
171
161
|
defaultStyle?: EmailBlockStyle;
|
|
172
162
|
/** Sample data used to render template HTML in the editor and preview. */
|
|
173
163
|
defaultData?: Record<string, unknown>;
|
|
174
|
-
/**
|
|
175
|
-
|
|
176
|
-
|
|
164
|
+
/** 默认画布直接编辑的 richText 字段;由字段声明解析生成。 */
|
|
165
|
+
inlineControl?: string;
|
|
166
|
+
/** Optional React inspector for controls that need domain-specific editing UI. */
|
|
167
|
+
inspector?: ComponentType<PluginEditorProps>;
|
|
168
|
+
/** Optional React canvas for multi-region or interactive editing. */
|
|
169
|
+
canvas?: ComponentType<PluginEditorProps>;
|
|
170
|
+
renderEmail: (ctx: BlockRenderContext) => string;
|
|
177
171
|
}
|
|
178
172
|
interface Variable {
|
|
179
173
|
/** 下拉展示并插入的变量,例如 `{{ store_name }}`。 */
|
|
@@ -184,6 +178,150 @@ interface Variable {
|
|
|
184
178
|
value?: string;
|
|
185
179
|
}
|
|
186
180
|
|
|
181
|
+
interface TemplateData {
|
|
182
|
+
[key: string]: unknown;
|
|
183
|
+
}
|
|
184
|
+
/** Resolves template HTML for the editor and preview while leaving stored source untouched. */
|
|
185
|
+
declare function renderTemplatePreview(html: string, defaultData?: TemplateData): string;
|
|
186
|
+
|
|
187
|
+
interface DocumentHtmlOptions {
|
|
188
|
+
resolveHtmlTemplates?: boolean;
|
|
189
|
+
variables?: Variable[];
|
|
190
|
+
templateData?: TemplateData;
|
|
191
|
+
}
|
|
192
|
+
declare function documentToHtml(document: EmailDocument, definitions?: readonly BlockDefinition[], options?: DocumentHtmlOptions): string;
|
|
193
|
+
|
|
194
|
+
declare const EMAIL_MARKUP: unique symbol;
|
|
195
|
+
interface EmailMarkup {
|
|
196
|
+
readonly [EMAIL_MARKUP]: true;
|
|
197
|
+
readonly html: string;
|
|
198
|
+
}
|
|
199
|
+
interface EmailImageOptions {
|
|
200
|
+
src: string;
|
|
201
|
+
alt?: string;
|
|
202
|
+
width?: string;
|
|
203
|
+
}
|
|
204
|
+
interface EmailButtonOptions {
|
|
205
|
+
href: string;
|
|
206
|
+
label: string;
|
|
207
|
+
}
|
|
208
|
+
interface EmailTools {
|
|
209
|
+
html: (strings: TemplateStringsArray, ...values: unknown[]) => EmailMarkup;
|
|
210
|
+
raw: (html: string) => EmailMarkup;
|
|
211
|
+
richText: (html: string) => EmailMarkup;
|
|
212
|
+
table: (rows: EmailMarkup[][]) => EmailMarkup;
|
|
213
|
+
image: (options: EmailImageOptions) => EmailMarkup;
|
|
214
|
+
button: (options: EmailButtonOptions) => EmailMarkup;
|
|
215
|
+
url: (value: string, image?: boolean) => string;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
type ControlKind = "text" | "textarea" | "html" | "richText" | "url" | "image" | "number" | "color" | "select" | "boolean" | "list" | "custom";
|
|
219
|
+
interface ControlComponentProps<T = unknown> {
|
|
220
|
+
value: T;
|
|
221
|
+
onChange: (value: T) => void;
|
|
222
|
+
label: string;
|
|
223
|
+
body: EmailBodySettings;
|
|
224
|
+
variables: Variable[];
|
|
225
|
+
}
|
|
226
|
+
interface ControlOptions<T> {
|
|
227
|
+
label: string;
|
|
228
|
+
defaultValue?: T;
|
|
229
|
+
placeholder?: string;
|
|
230
|
+
options?: ControlOption[];
|
|
231
|
+
rows?: number;
|
|
232
|
+
min?: number;
|
|
233
|
+
max?: number;
|
|
234
|
+
step?: number;
|
|
235
|
+
unit?: string;
|
|
236
|
+
profile?: RichTextProfile;
|
|
237
|
+
/** 由默认画布直接编辑此字段;多区域布局使用 Canvas + EditableRichText。 */
|
|
238
|
+
inline?: boolean;
|
|
239
|
+
component?: ComponentType<ControlComponentProps<T>>;
|
|
240
|
+
validate?: (value: T) => string | undefined;
|
|
241
|
+
}
|
|
242
|
+
/** 工厂生成的字段,同时负责默认值、运行时窄化和可选自定义控件。 */
|
|
243
|
+
interface ControlDefinition<T = unknown> extends Omit<ControlOptions<T>, "component" | "validate"> {
|
|
244
|
+
kind: ControlKind;
|
|
245
|
+
defaultValue: T;
|
|
246
|
+
read: (value: unknown) => T;
|
|
247
|
+
/** 只接收已归一化的字段值,不重复调用 read。 */
|
|
248
|
+
validateValue?: (value: unknown) => string | undefined;
|
|
249
|
+
/** value 已由宿主归一化。 */
|
|
250
|
+
renderControl?: (props: ControlComponentProps) => ReactNode;
|
|
251
|
+
itemControls?: ControlSchema;
|
|
252
|
+
}
|
|
253
|
+
type ControlSchema = Record<string, ControlDefinition>;
|
|
254
|
+
type ControlValues<Schema extends ControlSchema> = {
|
|
255
|
+
[Name in keyof Schema]: ReturnType<Schema[Name]["read"]>;
|
|
256
|
+
};
|
|
257
|
+
interface PluginEditorProps<Controls = Record<string, unknown>> {
|
|
258
|
+
block: EmailBlockNode;
|
|
259
|
+
controls: Controls;
|
|
260
|
+
style: EmailBlockStyle;
|
|
261
|
+
body: EmailBodySettings;
|
|
262
|
+
variables: Variable[];
|
|
263
|
+
selected: boolean;
|
|
264
|
+
renderedHtml: string;
|
|
265
|
+
select: () => void;
|
|
266
|
+
setControl: <Name extends keyof Controls & string>(name: Name, value: Controls[Name]) => void;
|
|
267
|
+
setControls: (patch: Partial<Controls>) => void;
|
|
268
|
+
setStyle: (id: string, value: string) => void;
|
|
269
|
+
}
|
|
270
|
+
interface PluginRenderContext<Controls> extends Omit<BlockRenderContext, "controls"> {
|
|
271
|
+
controls: Controls;
|
|
272
|
+
email: EmailTools;
|
|
273
|
+
}
|
|
274
|
+
interface BlockPluginOptions<Schema extends ControlSchema, Type extends string> {
|
|
275
|
+
type: Type;
|
|
276
|
+
title: string;
|
|
277
|
+
icon?: ReactNode | string;
|
|
278
|
+
description?: string;
|
|
279
|
+
override?: boolean;
|
|
280
|
+
controls?: Schema;
|
|
281
|
+
/** 默认 spacing + appearance;false 禁用默认容器控件。 */
|
|
282
|
+
containerStyles?: boolean | {
|
|
283
|
+
spacing?: boolean;
|
|
284
|
+
appearance?: boolean;
|
|
285
|
+
};
|
|
286
|
+
styleControls?: StyleControlConfig[];
|
|
287
|
+
inspectorSections?: BlockInspectorSection[];
|
|
288
|
+
defaultStyle?: EmailBlockStyle;
|
|
289
|
+
defaultData?: Record<string, unknown>;
|
|
290
|
+
Canvas?: ComponentType<PluginEditorProps<ControlValues<Schema>>>;
|
|
291
|
+
Inspector?: ComponentType<PluginEditorProps<ControlValues<Schema>>>;
|
|
292
|
+
renderEmail: (ctx: PluginRenderContext<ControlValues<Schema>>) => string | EmailMarkup;
|
|
293
|
+
}
|
|
294
|
+
/** 只通过 defineBlock 创建;配置同时用于编辑、节点创建和邮件导出。 */
|
|
295
|
+
interface BlockPlugin<Schema extends ControlSchema = ControlSchema, Type extends string = string> extends BlockDefinition {
|
|
296
|
+
type: Type;
|
|
297
|
+
schema: Schema;
|
|
298
|
+
}
|
|
299
|
+
interface ImagePickerContext {
|
|
300
|
+
value: string;
|
|
301
|
+
label: string;
|
|
302
|
+
signal: AbortSignal;
|
|
303
|
+
}
|
|
304
|
+
interface ValidationIssue {
|
|
305
|
+
blockId: string;
|
|
306
|
+
blockType: string;
|
|
307
|
+
controlPath: string;
|
|
308
|
+
message: string;
|
|
309
|
+
}
|
|
310
|
+
interface EmailEditorConfigOptions {
|
|
311
|
+
plugins?: BlockPlugin[];
|
|
312
|
+
/** false 隐藏全部内置区块;数组声明显示顺序。隐藏不影响已有节点渲染。 */
|
|
313
|
+
builtins?: false | string[];
|
|
314
|
+
pickImage?: (context: ImagePickerContext) => Promise<string | null>;
|
|
315
|
+
}
|
|
316
|
+
interface EmailEditorConfig {
|
|
317
|
+
readonly definitions: readonly BlockPlugin[];
|
|
318
|
+
readonly library: readonly BlockPlugin[];
|
|
319
|
+
readonly pickImage?: EmailEditorConfigOptions["pickImage"];
|
|
320
|
+
createBlock: (type: string) => EmailBlockNode;
|
|
321
|
+
toHtml: (document: EmailDocument, options?: DocumentHtmlOptions) => string;
|
|
322
|
+
validate: (document: EmailDocument) => ValidationIssue[];
|
|
323
|
+
}
|
|
324
|
+
|
|
187
325
|
interface EmailEditorData {
|
|
188
326
|
document: EmailDocument;
|
|
189
327
|
json: string;
|
|
@@ -199,13 +337,13 @@ interface EmailEditorHandle {
|
|
|
199
337
|
}
|
|
200
338
|
interface EmailEditorProps {
|
|
201
339
|
initialDocument?: EmailDocument;
|
|
202
|
-
/** External
|
|
203
|
-
|
|
204
|
-
|
|
340
|
+
/** External body settings. Incoming changes are applied to the open document. */
|
|
341
|
+
body?: Partial<EmailBodySettings>;
|
|
342
|
+
config?: EmailEditorConfig;
|
|
205
343
|
variables?: Variable[];
|
|
206
344
|
height?: number | string;
|
|
207
345
|
onChange?: (document: EmailDocument) => void;
|
|
208
|
-
|
|
346
|
+
onBodyChange?: (body: EmailBodySettings) => void;
|
|
209
347
|
}
|
|
210
348
|
|
|
211
349
|
declare const EmailEditor: react.ForwardRefExoticComponent<EmailEditorProps & react.RefAttributes<EmailEditorHandle>>;
|
|
@@ -217,91 +355,83 @@ interface RichTextInheritedStyle {
|
|
|
217
355
|
fontWeight: FontWeight;
|
|
218
356
|
lineHeight: string;
|
|
219
357
|
paragraphSpacing: string;
|
|
358
|
+
listSpacing?: string;
|
|
359
|
+
listIndent?: string;
|
|
360
|
+
linkColor?: string;
|
|
361
|
+
linkDecoration?: string;
|
|
220
362
|
}
|
|
221
363
|
|
|
222
364
|
interface RichTextProps {
|
|
223
365
|
initialHtml: string;
|
|
366
|
+
profile?: RichTextProfile;
|
|
224
367
|
placeholder?: string;
|
|
225
368
|
variables: Variable[];
|
|
226
369
|
selected: boolean;
|
|
370
|
+
toolbarId: string;
|
|
371
|
+
toolbarCollapsed: boolean;
|
|
227
372
|
inherited?: RichTextInheritedStyle;
|
|
228
373
|
onCommit: (html: string) => void;
|
|
229
374
|
onSelect: () => void;
|
|
230
375
|
}
|
|
231
|
-
declare function RichText({ initialHtml, placeholder, variables, selected, inherited, onCommit, onSelect, }: RichTextProps): react.JSX.Element;
|
|
376
|
+
declare function RichText({ initialHtml, profile, placeholder, variables, selected, toolbarId, toolbarCollapsed, inherited, onCommit, onSelect, }: RichTextProps): react.JSX.Element;
|
|
232
377
|
|
|
233
|
-
declare const DEFAULT_BLOCKS:
|
|
378
|
+
declare const DEFAULT_BLOCKS: BlockPlugin[];
|
|
234
379
|
|
|
235
|
-
declare function
|
|
380
|
+
declare function resolveEmailBody(body?: Partial<EmailBodySettings> | null): EmailBodySettings;
|
|
236
381
|
declare function createEmailDocument(blocks?: EmailBlockNode[]): EmailDocument;
|
|
237
382
|
|
|
238
|
-
declare function createBlockNode(type: string, definitions?: BlockDefinition[]): EmailBlockNode | null;
|
|
383
|
+
declare function createBlockNode(type: string, definitions?: readonly BlockDefinition[]): EmailBlockNode | null;
|
|
239
384
|
|
|
240
|
-
declare const
|
|
241
|
-
padding:
|
|
242
|
-
margin:
|
|
243
|
-
height:
|
|
385
|
+
declare const DIMENSION_CONTROLS: {
|
|
386
|
+
padding: StyleControlConfig;
|
|
387
|
+
margin: StyleControlConfig;
|
|
388
|
+
height: StyleControlConfig;
|
|
244
389
|
};
|
|
245
|
-
declare const
|
|
246
|
-
backgroundColor:
|
|
247
|
-
borderWidth:
|
|
248
|
-
borderStyle:
|
|
249
|
-
borderColor:
|
|
250
|
-
borderRadius:
|
|
390
|
+
declare const DECORATION_CONTROLS: {
|
|
391
|
+
backgroundColor: StyleControlConfig;
|
|
392
|
+
borderWidth: StyleControlConfig;
|
|
393
|
+
borderStyle: StyleControlConfig;
|
|
394
|
+
borderColor: StyleControlConfig;
|
|
395
|
+
borderRadius: StyleControlConfig;
|
|
251
396
|
};
|
|
252
|
-
declare const
|
|
253
|
-
fontFamily:
|
|
254
|
-
fontSize:
|
|
255
|
-
fontWeight:
|
|
256
|
-
lineHeight:
|
|
257
|
-
color:
|
|
258
|
-
textAlign:
|
|
259
|
-
paragraphSpacing:
|
|
260
|
-
listSpacing:
|
|
261
|
-
listIndent:
|
|
262
|
-
linkColor:
|
|
263
|
-
linkDecoration:
|
|
397
|
+
declare const TYPOGRAPHY_CONTROL_MAP: {
|
|
398
|
+
fontFamily: StyleControlConfig;
|
|
399
|
+
fontSize: StyleControlConfig;
|
|
400
|
+
fontWeight: StyleControlConfig;
|
|
401
|
+
lineHeight: StyleControlConfig;
|
|
402
|
+
color: StyleControlConfig;
|
|
403
|
+
textAlign: StyleControlConfig;
|
|
404
|
+
paragraphSpacing: StyleControlConfig;
|
|
405
|
+
listSpacing: StyleControlConfig;
|
|
406
|
+
listIndent: StyleControlConfig;
|
|
407
|
+
linkColor: StyleControlConfig;
|
|
408
|
+
linkDecoration: StyleControlConfig;
|
|
264
409
|
};
|
|
265
|
-
type
|
|
266
|
-
type
|
|
267
|
-
type
|
|
268
|
-
type
|
|
269
|
-
declare function
|
|
270
|
-
declare function
|
|
271
|
-
declare function
|
|
272
|
-
/** 容器字段按固定槽位合并。相同 id 使用调用方字段,其余字段按原顺序接在后面。返回值都是副本。 */
|
|
273
|
-
declare function resolveBlockStyleFields(fields?: StyleFieldConfig[], exactStyleFields?: boolean): StyleFieldConfig[];
|
|
274
|
-
|
|
275
|
-
interface TemplateData {
|
|
276
|
-
[key: string]: unknown;
|
|
277
|
-
}
|
|
278
|
-
/** Resolves template HTML for the editor and preview while leaving stored source untouched. */
|
|
279
|
-
declare function renderTemplatePreview(html: string, defaultData?: TemplateData): string;
|
|
280
|
-
|
|
281
|
-
interface DocumentHtmlOptions {
|
|
282
|
-
resolveHtmlTemplates?: boolean;
|
|
283
|
-
variables?: Variable[];
|
|
284
|
-
templateData?: TemplateData;
|
|
285
|
-
}
|
|
286
|
-
declare function documentToHtml(document: EmailDocument, definitions?: BlockDefinition[], options?: DocumentHtmlOptions): string;
|
|
410
|
+
type DimensionControlName = keyof typeof DIMENSION_CONTROLS;
|
|
411
|
+
type DecorationControlName = keyof typeof DECORATION_CONTROLS;
|
|
412
|
+
type TypographyControlName = keyof typeof TYPOGRAPHY_CONTROL_MAP;
|
|
413
|
+
type StyleControlOverrideMap<Name extends string> = Partial<Record<Name, Partial<StyleControlConfig>>>;
|
|
414
|
+
declare function createDimensionControls(overrides?: StyleControlOverrideMap<DimensionControlName>): Record<DimensionControlName, StyleControlConfig>;
|
|
415
|
+
declare function createDecorationControls(overrides?: StyleControlOverrideMap<DecorationControlName>): Record<DecorationControlName, StyleControlConfig>;
|
|
416
|
+
declare function createTypographyControls(overrides?: StyleControlOverrideMap<TypographyControlName>): Record<TypographyControlName, StyleControlConfig>;
|
|
287
417
|
|
|
288
418
|
interface BlockRenderOptions {
|
|
289
419
|
resolveHtmlTemplate?: boolean;
|
|
290
420
|
templateData?: TemplateData;
|
|
291
421
|
variables?: Variable[];
|
|
292
|
-
|
|
422
|
+
body?: EmailBodySettings;
|
|
293
423
|
}
|
|
294
424
|
type BlockRenderOptionsInput = BlockRenderOptions | boolean;
|
|
295
425
|
/** 用变量 name 里的字段名作为键,value 作为预览替换值。 */
|
|
296
426
|
declare function variablesToTemplateData(variables: Variable[]): TemplateData;
|
|
297
427
|
declare function mergeTemplateData(variables: Variable[], defaultData?: TemplateData): TemplateData | undefined;
|
|
298
|
-
declare function renderBlockContent(node: EmailBlockNode, definitions?: BlockDefinition[], mode?: RenderMode, options?: BlockRenderOptionsInput): string;
|
|
299
|
-
declare function renderBlock(node: EmailBlockNode, definitions?: BlockDefinition[], mode?: RenderMode,
|
|
300
|
-
declare function blockToHtml(node: EmailBlockNode, definitions?: BlockDefinition[], mode?: RenderMode, options?: BlockRenderOptionsInput): string;
|
|
428
|
+
declare function renderBlockContent(node: EmailBlockNode, definitions?: readonly BlockDefinition[], mode?: RenderMode, options?: BlockRenderOptionsInput): string;
|
|
429
|
+
declare function renderBlock(node: EmailBlockNode, definitions?: readonly BlockDefinition[], mode?: RenderMode, body?: EmailBodySettings): string;
|
|
430
|
+
declare function blockToHtml(node: EmailBlockNode, definitions?: readonly BlockDefinition[], mode?: RenderMode, options?: BlockRenderOptionsInput): string;
|
|
301
431
|
|
|
302
|
-
declare function buildRenderContext(node: EmailBlockNode, mode: RenderMode,
|
|
432
|
+
declare function buildRenderContext(node: EmailBlockNode, mode: RenderMode, body?: EmailBodySettings, definition?: BlockDefinition | undefined): BlockRenderContext;
|
|
303
433
|
|
|
304
|
-
declare function getBlockDefinition(type: string, definitions?: BlockDefinition[]): BlockDefinition | undefined;
|
|
434
|
+
declare function getBlockDefinition(type: string, definitions?: readonly BlockDefinition[]): BlockDefinition | undefined;
|
|
305
435
|
|
|
306
436
|
declare function generateId(prefix?: string): string;
|
|
307
437
|
|
|
@@ -322,4 +452,95 @@ declare const BLOCK_TYPES: {
|
|
|
322
452
|
};
|
|
323
453
|
type BuiltinBlockType = (typeof BLOCK_TYPES)[keyof typeof BLOCK_TYPES];
|
|
324
454
|
|
|
325
|
-
|
|
455
|
+
declare function defineBlock<Schema extends ControlSchema, const Type extends string>(input: BlockPluginOptions<Schema, Type>): BlockPlugin<Schema, Type>;
|
|
456
|
+
|
|
457
|
+
declare const EmailControls: {
|
|
458
|
+
text: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
459
|
+
textarea: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
460
|
+
richText: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
461
|
+
html: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
462
|
+
url: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
463
|
+
image: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
464
|
+
color: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
465
|
+
select: (options: ControlOptions<string>) => ControlDefinition<string>;
|
|
466
|
+
boolean: (options: ControlOptions<boolean>) => ControlDefinition<boolean>;
|
|
467
|
+
number: (options: ControlOptions<number>) => ControlDefinition<number>;
|
|
468
|
+
list<Schema extends ControlSchema>(options: ControlOptions<ControlValues<Schema>[]> & {
|
|
469
|
+
controls: Schema;
|
|
470
|
+
}): ControlDefinition<ControlValues<Schema>[]>;
|
|
471
|
+
custom<T>(options: ControlOptions<T> & {
|
|
472
|
+
defaultValue: T;
|
|
473
|
+
read: (value: unknown) => T;
|
|
474
|
+
component: NonNullable<ControlOptions<T>["component"]>;
|
|
475
|
+
}): ControlDefinition<T>;
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
declare function createEmailEditorConfig(options?: EmailEditorConfigOptions): EmailEditorConfig;
|
|
479
|
+
|
|
480
|
+
interface EditableRichTextProps {
|
|
481
|
+
control: string;
|
|
482
|
+
profile?: RichTextProfile;
|
|
483
|
+
placeholder?: string;
|
|
484
|
+
}
|
|
485
|
+
declare function EditableRichText({ control, profile, placeholder }: EditableRichTextProps): react.JSX.Element;
|
|
486
|
+
|
|
487
|
+
interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
|
|
488
|
+
type?: "text" | "url" | "email" | "search" | "tel" | "password" | "number";
|
|
489
|
+
}
|
|
490
|
+
declare const TextInput: react.ForwardRefExoticComponent<TextInputProps & react.RefAttributes<HTMLInputElement>>;
|
|
491
|
+
|
|
492
|
+
interface SelectControlProps {
|
|
493
|
+
id?: string;
|
|
494
|
+
label?: string;
|
|
495
|
+
value: string;
|
|
496
|
+
options: readonly ControlOption[];
|
|
497
|
+
emptyLabel?: string;
|
|
498
|
+
compact?: boolean;
|
|
499
|
+
disabled?: boolean;
|
|
500
|
+
onChange: (value: string) => void;
|
|
501
|
+
}
|
|
502
|
+
declare function SelectControl({ id, label, value, options, emptyLabel, compact, disabled, onChange }: SelectControlProps): react.JSX.Element;
|
|
503
|
+
|
|
504
|
+
interface CheckboxControlProps {
|
|
505
|
+
label: string;
|
|
506
|
+
checked: boolean;
|
|
507
|
+
disabled?: boolean;
|
|
508
|
+
className?: string;
|
|
509
|
+
variant?: "checkbox" | "switch";
|
|
510
|
+
onChange: (checked: boolean) => void;
|
|
511
|
+
}
|
|
512
|
+
declare function CheckboxControl({ label, checked, disabled, className, variant, onChange }: CheckboxControlProps): react.JSX.Element;
|
|
513
|
+
|
|
514
|
+
interface ColorControlProps {
|
|
515
|
+
value: string;
|
|
516
|
+
fallback?: string;
|
|
517
|
+
label?: string;
|
|
518
|
+
resetTo?: string;
|
|
519
|
+
onChange: (value: string) => void;
|
|
520
|
+
}
|
|
521
|
+
declare function ColorControl({ value, fallback, label, resetTo, onChange }: ColorControlProps): react.JSX.Element;
|
|
522
|
+
|
|
523
|
+
interface RangeControlProps {
|
|
524
|
+
id?: string;
|
|
525
|
+
label?: string;
|
|
526
|
+
value: number;
|
|
527
|
+
min?: number;
|
|
528
|
+
max?: number;
|
|
529
|
+
step?: number;
|
|
530
|
+
onChange: (value: number) => void;
|
|
531
|
+
}
|
|
532
|
+
declare function RangeControl({ id, label, value, min, max, step, onChange, }: RangeControlProps): react.JSX.Element;
|
|
533
|
+
|
|
534
|
+
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
535
|
+
variant?: "default" | "primary" | "solid" | "icon";
|
|
536
|
+
tooltip?: string;
|
|
537
|
+
}
|
|
538
|
+
declare function Button({ type, variant, className, tooltip, children, "aria-describedby": describedBy, ...props }: ButtonProps): react.JSX.Element;
|
|
539
|
+
|
|
540
|
+
interface ControlEditorProps {
|
|
541
|
+
control: string;
|
|
542
|
+
}
|
|
543
|
+
/** 自定义 Inspector 复用字段声明、资源选择器、校验和标准控件。 */
|
|
544
|
+
declare function ControlEditor({ control }: ControlEditorProps): react.JSX.Element;
|
|
545
|
+
|
|
546
|
+
export { BLOCK_TYPES, BORDER_STYLES, type BlockInspectorSection, type BlockPlugin, type BlockPluginOptions, type BlockRenderContext, type BlockRenderOptions, type BorderStyle, type BuiltinBlockType, Button, CheckboxControl, ColorControl, type ControlComponentProps, type ControlDefinition, ControlEditor, type ControlEditorProps, type ControlKind, type ControlOption, type ControlOptions, type ControlSchema, type ControlValues, DEFAULT_BLOCKS, DEFAULT_EMAIL_BODY, DOCUMENT_VERSION, type DecorationControlName, type DimensionControlName, type DocumentHtmlOptions, EditableRichText, type EditableRichTextProps, type EmailBlockNode, type EmailBlockStyle, type EmailBodySettings, EmailControls, type EmailDecorationStyle, type EmailDocument, EmailEditor, type EmailEditorConfig, type EmailEditorConfigOptions, type EmailEditorData, type EmailEditorHandle, type EmailEditorProps, type EmailElementStyle, type EmailMarkup, type EmailSpacingStyle, type EmailTools, type EmailTypographyStyle, FONT_FAMILIES, FONT_WEIGHTS, type FontWeight, HORIZONTAL_ALIGNS, type HorizontalAlign, type ImagePickerContext, LINK_DECORATIONS, type LinkDecoration, type PluginEditorProps, type PluginRenderContext, RangeControl, type RenderMode, RichText, type RichTextProfile, STYLE_GROUPS, SelectControl, type StyleControlConfig, type StyleControlType, type StyleGroup, TEXT_ALIGNS, type TemplateData, type TextAlign, TextInput, type TypographyControlName, type ValidationIssue, type Variable, blockToHtml, buildRenderContext, createBlockNode, createDecorationControls, createDimensionControls, createEmailDocument, createEmailEditorConfig, createTypographyControls, defineBlock, documentToHtml, generateId, getBlockDefinition, mergeTemplateData, renderBlock, renderBlockContent, renderTemplatePreview, resolveEmailBody, variablesToTemplateData };
|