@pexelize/react-editor 1.0.5 → 2.0.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 +574 -64
- package/dist/index.d.ts +201 -215
- package/dist/index.esm.js +111 -304
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +109 -303
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,127 +1,637 @@
|
|
|
1
1
|
# @pexelize/react-editor
|
|
2
2
|
|
|
3
|
-
React wrapper
|
|
3
|
+
React wrapper for the [Pexelize Editor](https://pexelize.com) - a drag-and-drop email and page builder.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @pexelize/react-editor
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { useRef, useState } from "react";
|
|
15
|
+
import {
|
|
16
|
+
PexelizeEditor,
|
|
17
|
+
PexelizeEditorRef,
|
|
18
|
+
DesignJson,
|
|
19
|
+
} from "@pexelize/react-editor";
|
|
16
20
|
|
|
17
21
|
function EmailBuilder() {
|
|
18
22
|
const editorRef = useRef<PexelizeEditorRef>(null);
|
|
23
|
+
const [lastSaved, setLastSaved] = useState<Date | null>(null);
|
|
19
24
|
|
|
20
|
-
const
|
|
21
|
-
editorRef.current?.
|
|
22
|
-
|
|
25
|
+
const handleExport = async () => {
|
|
26
|
+
const editor = editorRef.current?.editor;
|
|
27
|
+
if (!editor) return;
|
|
28
|
+
|
|
29
|
+
const { html, design } = await editor.exportHtmlAsync();
|
|
30
|
+
console.log("HTML:", html);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleSave = async () => {
|
|
34
|
+
const editor = editorRef.current?.editor;
|
|
35
|
+
if (!editor) return;
|
|
36
|
+
|
|
37
|
+
const design = await editor.getDesign();
|
|
38
|
+
await saveToBackend(design);
|
|
39
|
+
setLastSaved(new Date());
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div style={{ height: "100vh", display: "flex", flexDirection: "column" }}>
|
|
44
|
+
<div style={{ padding: 16, borderBottom: "1px solid #eee" }}>
|
|
45
|
+
<button onClick={handleExport}>Export HTML</button>
|
|
46
|
+
<button onClick={handleSave}>Save</button>
|
|
47
|
+
{lastSaved && <span>Last saved: {lastSaved.toLocaleTimeString()}</span>}
|
|
48
|
+
</div>
|
|
49
|
+
<PexelizeEditor
|
|
50
|
+
ref={editorRef}
|
|
51
|
+
editorId={123}
|
|
52
|
+
apiKey="your-api-key"
|
|
53
|
+
height="100%"
|
|
54
|
+
options={{ editorMode: "email" }}
|
|
55
|
+
onReady={(editor) => {
|
|
56
|
+
console.log("Editor ready!");
|
|
57
|
+
// Load initial design if available
|
|
58
|
+
// editor.loadDesign(savedDesign);
|
|
59
|
+
}}
|
|
60
|
+
onLoad={() => console.log("Design loaded")}
|
|
61
|
+
onChange={(data) => {
|
|
62
|
+
console.log("Design changed:", data.type);
|
|
63
|
+
// Auto-save or mark as dirty
|
|
64
|
+
}}
|
|
65
|
+
onError={(error) => console.error("Editor error:", error)}
|
|
66
|
+
/>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Complete Example with All Features
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useRef, useState, useCallback } from "react";
|
|
76
|
+
import {
|
|
77
|
+
PexelizeEditor,
|
|
78
|
+
PexelizeEditorRef,
|
|
79
|
+
DesignJson,
|
|
80
|
+
MergeTag,
|
|
81
|
+
} from "@pexelize/react-editor";
|
|
82
|
+
|
|
83
|
+
function AdvancedEmailBuilder() {
|
|
84
|
+
const editorRef = useRef<PexelizeEditorRef>(null);
|
|
85
|
+
const [isDirty, setIsDirty] = useState(false);
|
|
86
|
+
|
|
87
|
+
// Merge tags for personalization
|
|
88
|
+
const mergeTags: MergeTag[] = [
|
|
89
|
+
{ name: "First Name", value: "{{first_name}}" },
|
|
90
|
+
{ name: "Last Name", value: "{{last_name}}" },
|
|
91
|
+
{ name: "Company", value: "{{company}}" },
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const handleReady = useCallback((editor) => {
|
|
95
|
+
console.log("Editor initialized");
|
|
96
|
+
|
|
97
|
+
// Set merge tags
|
|
98
|
+
editor.setMergeTags(mergeTags);
|
|
99
|
+
|
|
100
|
+
// Set custom fonts
|
|
101
|
+
editor.setFonts({
|
|
102
|
+
showDefaultFonts: true,
|
|
103
|
+
customFonts: [{ label: "Brand Font", value: "BrandFont, sans-serif" }],
|
|
23
104
|
});
|
|
105
|
+
|
|
106
|
+
// Load saved design or start blank
|
|
107
|
+
const savedDesign = localStorage.getItem("email-design");
|
|
108
|
+
if (savedDesign) {
|
|
109
|
+
editor.loadDesign(JSON.parse(savedDesign));
|
|
110
|
+
}
|
|
111
|
+
}, []);
|
|
112
|
+
|
|
113
|
+
const handleChange = useCallback(
|
|
114
|
+
(data: { design: DesignJson; type: string }) => {
|
|
115
|
+
setIsDirty(true);
|
|
116
|
+
// Auto-save to localStorage
|
|
117
|
+
localStorage.setItem("email-design", JSON.stringify(data.design));
|
|
118
|
+
},
|
|
119
|
+
[],
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const handleExportHtml = async () => {
|
|
123
|
+
const editor = editorRef.current?.editor;
|
|
124
|
+
if (!editor) return;
|
|
125
|
+
|
|
126
|
+
const { html, design } = await editor.exportHtmlAsync();
|
|
127
|
+
|
|
128
|
+
// Download HTML file
|
|
129
|
+
const blob = new Blob([html], { type: "text/html" });
|
|
130
|
+
const url = URL.createObjectURL(blob);
|
|
131
|
+
const a = document.createElement("a");
|
|
132
|
+
a.href = url;
|
|
133
|
+
a.download = "email.html";
|
|
134
|
+
a.click();
|
|
24
135
|
};
|
|
25
136
|
|
|
26
|
-
const
|
|
27
|
-
editorRef.current?.
|
|
28
|
-
|
|
137
|
+
const handleExportImage = () => {
|
|
138
|
+
const editor = editorRef.current?.editor;
|
|
139
|
+
if (!editor) return;
|
|
140
|
+
|
|
141
|
+
editor.exportImage((data) => {
|
|
142
|
+
window.open(data.url, "_blank");
|
|
29
143
|
});
|
|
30
144
|
};
|
|
31
145
|
|
|
146
|
+
const handlePreview = () => {
|
|
147
|
+
const editor = editorRef.current?.editor;
|
|
148
|
+
editor?.showPreview("desktop");
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const handleUndo = () => editorRef.current?.editor?.undo();
|
|
152
|
+
const handleRedo = () => editorRef.current?.editor?.redo();
|
|
153
|
+
|
|
32
154
|
return (
|
|
33
|
-
<div>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
155
|
+
<div style={{ height: "100vh", display: "flex", flexDirection: "column" }}>
|
|
156
|
+
{/* Toolbar */}
|
|
157
|
+
<div
|
|
158
|
+
style={{
|
|
159
|
+
padding: 12,
|
|
160
|
+
borderBottom: "1px solid #ddd",
|
|
161
|
+
display: "flex",
|
|
162
|
+
gap: 8,
|
|
163
|
+
}}
|
|
164
|
+
>
|
|
165
|
+
<button onClick={handleUndo}>Undo</button>
|
|
166
|
+
<button onClick={handleRedo}>Redo</button>
|
|
167
|
+
<button onClick={handlePreview}>Preview</button>
|
|
168
|
+
<button onClick={handleExportHtml}>Export HTML</button>
|
|
169
|
+
<button onClick={handleExportImage}>Export Image</button>
|
|
170
|
+
{isDirty && <span style={{ color: "orange" }}>● Unsaved changes</span>}
|
|
37
171
|
</div>
|
|
38
172
|
|
|
173
|
+
{/* Editor */}
|
|
39
174
|
<PexelizeEditor
|
|
40
175
|
ref={editorRef}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
176
|
+
editorId={123}
|
|
177
|
+
apiKey="your-api-key"
|
|
178
|
+
height="100%"
|
|
179
|
+
editorMode="email"
|
|
180
|
+
options={{
|
|
181
|
+
appearance: { theme: "light" },
|
|
182
|
+
features: {
|
|
183
|
+
preview: true,
|
|
184
|
+
undoRedo: true,
|
|
185
|
+
imageEditor: true,
|
|
186
|
+
},
|
|
187
|
+
}}
|
|
188
|
+
onReady={handleReady}
|
|
189
|
+
onChange={handleChange}
|
|
190
|
+
onError={(error) => alert(`Error: ${error.message}`)}
|
|
45
191
|
/>
|
|
46
192
|
</div>
|
|
47
193
|
);
|
|
48
194
|
}
|
|
195
|
+
|
|
196
|
+
export default AdvancedEmailBuilder;
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Props
|
|
200
|
+
|
|
201
|
+
| Prop | Type | Required | Description |
|
|
202
|
+
| ------------- | ------------------- | -------- | -------------------------------------------------------- |
|
|
203
|
+
| `editorId` | `number \| string` | ✅ | Editor ID from your Pexelize dashboard |
|
|
204
|
+
| `apiKey` | `string` | ✅ | API key from your Pexelize dashboard |
|
|
205
|
+
| `templateId` | `string` | ❌ | Template ID for AI Copilot history |
|
|
206
|
+
| `design` | `DesignJson` | ❌ | Initial design to load |
|
|
207
|
+
| `editorMode` | `EditorMode` | ❌ | `'email'` \| `'web'` \| `'popup'` |
|
|
208
|
+
| `contentType` | `EditorContentType` | ❌ | `'page'` \| `'module'` |
|
|
209
|
+
| `ai` | `AIConfig` | ❌ | AI features configuration |
|
|
210
|
+
| `height` | `string \| number` | ❌ | Editor height (default: `'600px'`) |
|
|
211
|
+
| `options` | `PexelizeConfig` | ❌ | SDK configuration options |
|
|
212
|
+
| `className` | `string` | ❌ | CSS class for the container |
|
|
213
|
+
| `style` | `CSSProperties` | ❌ | Inline styles for the container |
|
|
214
|
+
| `onReady` | `(editor) => void` | ❌ | Called when editor is ready |
|
|
215
|
+
| `onLoad` | `() => void` | ❌ | Called when design is loaded |
|
|
216
|
+
| `onChange` | `(data) => void` | ❌ | Called when design changes (receives `{ design, type }`) |
|
|
217
|
+
| `onError` | `(error) => void` | ❌ | Called on initialization error |
|
|
218
|
+
|
|
219
|
+
## SDK Methods Reference
|
|
220
|
+
|
|
221
|
+
Access the SDK via `editorRef.current?.editor`:
|
|
222
|
+
|
|
223
|
+
### Design Methods
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
// Load/save design
|
|
227
|
+
editor.loadDesign(design);
|
|
228
|
+
editor.loadDesign(design, { preserveHistory: false });
|
|
229
|
+
await editor.loadDesignAsync(design);
|
|
230
|
+
editor.loadBlank();
|
|
231
|
+
editor.saveDesign((design) => console.log(design));
|
|
232
|
+
const design = await editor.getDesign();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Export Methods
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
// HTML export
|
|
239
|
+
editor.exportHtml((data) => console.log(data.html, data.design));
|
|
240
|
+
const { html, design, chunks } = await editor.exportHtmlAsync();
|
|
241
|
+
|
|
242
|
+
// Plain text export
|
|
243
|
+
editor.exportPlainText((data) => console.log(data.text));
|
|
244
|
+
const { text, design } = await editor.exportPlainTextAsync();
|
|
245
|
+
|
|
246
|
+
// Image export
|
|
247
|
+
editor.exportImage((data) => console.log(data.url), { format: "png" });
|
|
248
|
+
|
|
249
|
+
// PDF export
|
|
250
|
+
editor.exportPdf((data) => console.log(data.url), { format: "A4" });
|
|
251
|
+
|
|
252
|
+
// ZIP export
|
|
253
|
+
editor.exportZip((data) => console.log(data.url));
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Merge Tags
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
editor.setMergeTags([
|
|
260
|
+
{ name: "First Name", value: "{{first_name}}" },
|
|
261
|
+
{ name: "Company", value: "{{company}}" },
|
|
262
|
+
]);
|
|
263
|
+
const tags = await editor.getMergeTags();
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Design Tags
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
editor.setDesignTags({ brand_color: "#007bff" });
|
|
270
|
+
const tags = await editor.getDesignTags();
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Special Links
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
editor.setSpecialLinks([{ name: "Unsubscribe", href: "{{unsubscribe_url}}" }]);
|
|
277
|
+
const links = await editor.getSpecialLinks();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Modules
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
editor.setModules(modules);
|
|
284
|
+
const modules = await editor.getModules();
|
|
285
|
+
await editor.addModule(module);
|
|
286
|
+
await editor.removeModule(moduleId);
|
|
287
|
+
editor.updateModule(moduleId, rowData);
|
|
288
|
+
const syncedIds = await editor.getSyncedModulesInDesign();
|
|
289
|
+
await editor.unlinkSyncedModule(rowId);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Fonts
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
editor.setFonts({
|
|
296
|
+
showDefaultFonts: true,
|
|
297
|
+
customFonts: [{ label: "Custom Font", value: "CustomFont" }],
|
|
298
|
+
});
|
|
299
|
+
const fonts = await editor.getFonts();
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Body Values
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
editor.setBodyValues({
|
|
306
|
+
backgroundColor: "#f5f5f5",
|
|
307
|
+
contentWidth: "600px",
|
|
308
|
+
});
|
|
309
|
+
const values = await editor.getBodyValues();
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Editor Options
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
editor.setOptions({
|
|
316
|
+
display: { backgroundColor: "#f5f5f5", contentWidth: 600 },
|
|
317
|
+
links: { color: "#0066cc", underline: true },
|
|
318
|
+
buttonDefaults: { backgroundColor: "#3AAEE0" },
|
|
319
|
+
appearance: { theme: "auto", accentColor: "indigo" },
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Tools Configuration
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
editor.setToolsConfig({
|
|
327
|
+
heading: { enabled: true },
|
|
328
|
+
button: { properties: { colors: { value: { backgroundColor: "#007bff" } } } },
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Tabs Management
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
editor.updateTabs({
|
|
336
|
+
myCustomTab: { enabled: true, position: 1, icon: "star", active: true },
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Editor Mode & Config
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
editor.setEditorMode("email"); // 'email' | 'web' | 'popup' | 'document'
|
|
344
|
+
editor.setEditorConfig({
|
|
345
|
+
minRows: 1,
|
|
346
|
+
maxRows: 1,
|
|
347
|
+
contentType: "module",
|
|
348
|
+
autoSelectOnDrop: true,
|
|
349
|
+
});
|
|
350
|
+
const config = await editor.getEditorConfig();
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Locale & Language
|
|
354
|
+
|
|
355
|
+
```tsx
|
|
356
|
+
editor.setLocale("en-US");
|
|
357
|
+
editor.setCurrentLanguage("es-ES");
|
|
358
|
+
editor.setLanguages([
|
|
359
|
+
{ label: "English", value: "en-US", default: true },
|
|
360
|
+
{ label: "Español", value: "es-ES" },
|
|
361
|
+
]);
|
|
362
|
+
const lang = await editor.getCurrentLanguage();
|
|
363
|
+
editor.setTextDirection("rtl");
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Appearance
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
editor.setAppearance({
|
|
370
|
+
theme: "dark",
|
|
371
|
+
panels: { tools: { position: "left" } },
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Custom CSS/JS
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
editor.setCustomCSS(["https://example.com/styles.css"]);
|
|
379
|
+
editor.setCustomJS(["https://example.com/script.js"]);
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Preview
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
editor.showPreview("desktop"); // 'desktop' | 'tablet' | 'mobile'
|
|
386
|
+
editor.hidePreview();
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Undo/Redo
|
|
390
|
+
|
|
391
|
+
```tsx
|
|
392
|
+
editor.undo();
|
|
393
|
+
editor.redo();
|
|
394
|
+
const canUndo = await editor.canUndo();
|
|
395
|
+
const canRedo = await editor.canRedo();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Save
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
editor.save(); // Triggers save callback
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Element Manipulation
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
editor.execCommand({
|
|
408
|
+
action: "highlight",
|
|
409
|
+
target: { type: "row", id: "row-123" },
|
|
410
|
+
});
|
|
411
|
+
editor.selectElement({ type: "row", id: "row-123" });
|
|
412
|
+
editor.highlightElement({ type: "content", id: "content-789" });
|
|
413
|
+
editor.highlightElement(null); // Clear highlight
|
|
414
|
+
editor.scrollToElement({ type: "row", id: "row-123" });
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Events
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
const unsubscribe = editor.addEventListener("design:updated", (data) => {
|
|
421
|
+
console.log("Design changed:", data);
|
|
422
|
+
});
|
|
423
|
+
editor.removeEventListener("design:updated", callback);
|
|
49
424
|
```
|
|
50
425
|
|
|
51
|
-
|
|
426
|
+
**Available Events:**
|
|
52
427
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
| `onReady` | `() => void` | - | Called when editor is ready |
|
|
61
|
-
| `onChange` | `(data) => void` | - | Called when design changes |
|
|
62
|
-
| `onLoad` | `(data) => void` | - | Called when design is loaded |
|
|
63
|
-
| `onImage` | `ImageUploadCallback` | - | Image upload handler |
|
|
64
|
-
| `onSave` | `SaveCallback` | - | Save handler |
|
|
428
|
+
- `editor:ready` - Editor initialized
|
|
429
|
+
- `design:loaded` - Design loaded
|
|
430
|
+
- `design:updated` - Design changed
|
|
431
|
+
- `element:selected` - Element selected
|
|
432
|
+
- `save` - Save triggered
|
|
433
|
+
- `preview:shown` / `preview:hidden` - Preview toggled
|
|
434
|
+
- `image:uploaded` / `image:error` - Image upload events
|
|
65
435
|
|
|
66
|
-
|
|
436
|
+
### Callbacks
|
|
67
437
|
|
|
68
|
-
|
|
438
|
+
```tsx
|
|
439
|
+
editor.registerCallback("image", (file, done) => {
|
|
440
|
+
uploadToMyServer(file).then((url) => done({ url }));
|
|
441
|
+
});
|
|
442
|
+
editor.registerCallback("save", (data, done) => {
|
|
443
|
+
saveToBackend(data).then(() => done({ success: true }));
|
|
444
|
+
});
|
|
445
|
+
editor.registerCallback("linkClick", (data, done) => {
|
|
446
|
+
done({ url: data.url, target: "_blank" });
|
|
447
|
+
});
|
|
448
|
+
editor.unregisterCallback("image");
|
|
449
|
+
|
|
450
|
+
// Shorthand methods
|
|
451
|
+
editor.onSave(callback);
|
|
452
|
+
editor.offSave();
|
|
453
|
+
editor.onChange(callback);
|
|
454
|
+
editor.onLoad(callback);
|
|
455
|
+
editor.onModuleSave(callback);
|
|
456
|
+
editor.onSyncedModuleUpdate(callback);
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Tool Registration
|
|
69
460
|
|
|
70
461
|
```tsx
|
|
71
|
-
|
|
462
|
+
await editor.registerTool({
|
|
463
|
+
id: "myCustomTool",
|
|
464
|
+
label: "My Tool",
|
|
465
|
+
baseToolType: "text",
|
|
466
|
+
icon: "star",
|
|
467
|
+
properties: { ... },
|
|
468
|
+
});
|
|
469
|
+
await editor.unregisterTool("myCustomTool");
|
|
470
|
+
const tools = await editor.getTools();
|
|
471
|
+
```
|
|
72
472
|
|
|
73
|
-
|
|
74
|
-
editorRef.current?.loadDesign(myDesign);
|
|
473
|
+
### State
|
|
75
474
|
|
|
76
|
-
|
|
77
|
-
|
|
475
|
+
```tsx
|
|
476
|
+
const state = await editor.getState();
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Collaboration
|
|
480
|
+
|
|
481
|
+
```tsx
|
|
482
|
+
editor.setCollaborationConfig({
|
|
483
|
+
enabled: true,
|
|
484
|
+
threadPreview: true,
|
|
485
|
+
user: { id: "user-123", name: "John Doe" },
|
|
486
|
+
});
|
|
487
|
+
```
|
|
78
488
|
|
|
79
|
-
|
|
80
|
-
const design = await editorRef.current?.getDesign();
|
|
489
|
+
### Utility Methods
|
|
81
490
|
|
|
82
|
-
|
|
83
|
-
|
|
491
|
+
```tsx
|
|
492
|
+
editor.registerColumns([1, 2, 1]); // 1:2:1 layout
|
|
493
|
+
editor.setColorPickerConfig({
|
|
494
|
+
colors: ["#FF0000", "#00FF00", "#0000FF"],
|
|
495
|
+
recentColors: true,
|
|
496
|
+
});
|
|
497
|
+
editor.setStyleGuide({
|
|
498
|
+
tools: {
|
|
499
|
+
heading: {
|
|
500
|
+
styles: {
|
|
501
|
+
h1: { label: "Heading 1", values: { fontSize: "32px" } },
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
```
|
|
84
507
|
|
|
85
|
-
|
|
86
|
-
editorRef.current?.exportHtml((data) => console.log(data.html));
|
|
508
|
+
### Validation & Audit
|
|
87
509
|
|
|
88
|
-
|
|
89
|
-
const
|
|
510
|
+
```tsx
|
|
511
|
+
const result = await editor.validateTemplate(data, { strict: true, detailed: true });
|
|
512
|
+
editor.validateTemplateCallback(data, (result) => console.log(result));
|
|
513
|
+
const toolResult = await editor.validateTool(data, { toolType: "button" });
|
|
514
|
+
const toolTypes = await editor.getToolTypes();
|
|
90
515
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
516
|
+
editor.setValidator((info) => {
|
|
517
|
+
if (!info.html.includes("alt=")) {
|
|
518
|
+
return [{ id: "missing-alt", title: "Missing Alt Text", severity: "WARNING" }];
|
|
519
|
+
}
|
|
520
|
+
return [];
|
|
521
|
+
});
|
|
522
|
+
editor.setToolValidator("image", (info) => { ... });
|
|
523
|
+
editor.clearValidators();
|
|
94
524
|
|
|
95
|
-
|
|
96
|
-
const ready = editorRef.current?.isReady();
|
|
525
|
+
const auditResult = await editor.audit();
|
|
97
526
|
```
|
|
98
527
|
|
|
99
|
-
|
|
528
|
+
### Display Conditions
|
|
529
|
+
|
|
530
|
+
```tsx
|
|
531
|
+
editor.setDisplayConditions({
|
|
532
|
+
enabled: true,
|
|
533
|
+
conditions: [
|
|
534
|
+
{
|
|
535
|
+
type: "Customer Segment",
|
|
536
|
+
label: "VIP Members",
|
|
537
|
+
before: '{% if customer.tier == "VIP" %}',
|
|
538
|
+
after: "{% endif %}",
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
});
|
|
542
|
+
```
|
|
100
543
|
|
|
101
|
-
|
|
544
|
+
### Image Upload
|
|
102
545
|
|
|
103
546
|
```tsx
|
|
104
|
-
|
|
547
|
+
const result = await editor.uploadImage(file, {
|
|
548
|
+
folderId: "folder-123",
|
|
549
|
+
altText: "Description",
|
|
550
|
+
onProgress: (progress) => console.log(`${progress.percent}%`),
|
|
551
|
+
});
|
|
552
|
+
```
|
|
105
553
|
|
|
106
|
-
|
|
107
|
-
const { sdk, isReady, isLoading, error } = usePexelizeSDK({
|
|
108
|
-
containerId: 'my-editor',
|
|
109
|
-
editorMode: 'email',
|
|
110
|
-
});
|
|
554
|
+
### Asset Management
|
|
111
555
|
|
|
112
|
-
|
|
113
|
-
|
|
556
|
+
```tsx
|
|
557
|
+
const { assets, total } = await editor.listAssets({
|
|
558
|
+
folderId: "folder-123",
|
|
559
|
+
page: 1,
|
|
560
|
+
});
|
|
561
|
+
const deleteResult = await editor.deleteAsset(assetId);
|
|
562
|
+
const folders = await editor.listAssetFolders(parentId);
|
|
563
|
+
const folder = await editor.createAssetFolder("New Folder", parentId);
|
|
564
|
+
const storageInfo = await editor.getStorageInfo();
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### AI Image
|
|
568
|
+
|
|
569
|
+
```tsx
|
|
570
|
+
const result = await editor.saveAiImage(base64Data, {
|
|
571
|
+
prompt: "A sunset over mountains",
|
|
572
|
+
style: "realism",
|
|
573
|
+
suggestedFilename: "ai-sunset.png",
|
|
574
|
+
});
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Storage & AI Utilities
|
|
578
|
+
|
|
579
|
+
```tsx
|
|
580
|
+
editor.isExternalStorage();
|
|
581
|
+
editor.canSaveAiImages();
|
|
582
|
+
editor.getAssetStorageMode(); // 'pexelize' | 'external'
|
|
583
|
+
editor.isAIDisabled();
|
|
584
|
+
editor.isAIFeatureEnabledCheck("copilot");
|
|
585
|
+
editor.isAIFeatureExternalCheck("imageGeneration");
|
|
586
|
+
editor.getAIFeatureModeCheck("smartHeading"); // 'pexelize' | 'external' | 'disabled'
|
|
587
|
+
editor.getAIMode();
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### Status
|
|
591
|
+
|
|
592
|
+
```tsx
|
|
593
|
+
editor.isInitialized();
|
|
594
|
+
editor.isReady();
|
|
595
|
+
editor.destroy();
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
## Hook API
|
|
599
|
+
|
|
600
|
+
```tsx
|
|
601
|
+
import { PexelizeEditor, usePexelizeEditor } from "@pexelize/react-editor";
|
|
602
|
+
|
|
603
|
+
function MyEditor() {
|
|
604
|
+
const { ref, editor, isReady, isLoading, error } = usePexelizeEditor();
|
|
114
605
|
|
|
115
606
|
return (
|
|
116
607
|
<div>
|
|
117
|
-
<div id='my-editor' style={{ height: '600px' }} />
|
|
118
608
|
<button
|
|
609
|
+
onClick={() => editor?.exportHtml(console.log)}
|
|
119
610
|
disabled={!isReady}
|
|
120
|
-
onClick={() => sdk?.exportHtml((d) => console.log(d.html))}
|
|
121
611
|
>
|
|
122
612
|
Export
|
|
123
613
|
</button>
|
|
614
|
+
<PexelizeEditor ref={ref} editorId={123} apiKey="your-api-key" />
|
|
124
615
|
</div>
|
|
125
616
|
);
|
|
126
617
|
}
|
|
127
618
|
```
|
|
619
|
+
|
|
620
|
+
## TypeScript
|
|
621
|
+
|
|
622
|
+
All SDK types are re-exported:
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
import type {
|
|
626
|
+
PexelizeConfig,
|
|
627
|
+
DesignJson,
|
|
628
|
+
ExportHtmlData,
|
|
629
|
+
MergeTag,
|
|
630
|
+
EditorEventName,
|
|
631
|
+
AIConfig,
|
|
632
|
+
} from "@pexelize/react-editor";
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
## License
|
|
636
|
+
|
|
637
|
+
MIT
|