dragble-react-editor 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dragble
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,533 @@
1
+ <p align="center">
2
+ <a href="https://dragble.com">
3
+ <img src="logo.png" alt="Dragble Email Editor - React Email Template Builder" width="300" />
4
+ </a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/dragble-react-editor"><img src="https://img.shields.io/npm/v/dragble-react-editor.svg" alt="npm version" /></a>
9
+ <a href="https://github.com/Dragble/dragble-react-editor/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license" /></a>
10
+ </p>
11
+
12
+ # dragble-react-editor
13
+
14
+ React component for building **email templates** with drag-and-drop. Embed a full-featured **email editor** into your React app — create responsive HTML emails, newsletters, transactional email templates, and email marketing campaigns visually without writing code.
15
+
16
+ [Dragble](https://dragble.com) is a modern **email builder** and **email template editor** that lets your users design professional emails with a visual drag-and-drop interface.
17
+
18
+ [Website](https://dragble.com) | [Documentation](https://docs.dragble.com) | [Dashboard](https://developers.dragble.com)
19
+
20
+ <p align="center">
21
+ <img src="editor_image.png" alt="Dragble React Email Editor - Drag and Drop Email Template Builder" width="700" />
22
+ </p>
23
+
24
+ ## Features
25
+
26
+ - Drag-and-drop **email template builder** with 20+ content blocks
27
+ - Responsive **HTML email** output compatible with all major email clients
28
+ - **Newsletter editor** with merge tags, dynamic content, and display conditions
29
+ - Visual **email designer** — no HTML/CSS knowledge required for end users
30
+ - Export to HTML, JSON, image, PDF, or ZIP
31
+ - Built-in image editor, AI content generation, and collaboration tools
32
+ - Full TypeScript support
33
+ - Lightweight React wrapper — just a single component or hook
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ # npm
39
+ npm install dragble-react-editor
40
+
41
+ # yarn
42
+ yarn add dragble-react-editor
43
+
44
+ # pnpm
45
+ pnpm add dragble-react-editor
46
+ ```
47
+
48
+ ## Editor Key
49
+
50
+ An `editorKey` is required to use the editor. You can get one by creating a project on the [Dragble Developer Dashboard](https://developers.dragble.com).
51
+
52
+ ## Quick Start
53
+
54
+ ```tsx
55
+ import { useRef } from "react";
56
+ import { DragbleEditor, DragbleEditorRef, DesignJson } from "dragble-react-editor";
57
+
58
+ function EmailBuilder() {
59
+ const editorRef = useRef<DragbleEditorRef>(null);
60
+
61
+ const handleChange = async (data: { design: DesignJson; type: string }) => {
62
+ // Design JSON is available directly from the callback
63
+ const json = data.design;
64
+ console.log("Design JSON:", json);
65
+
66
+ // To get HTML, call exportHtml on the editor
67
+ const html = await editorRef.current?.editor?.exportHtml();
68
+ console.log("HTML:", html);
69
+ };
70
+
71
+ return (
72
+ <div style={{ height: "100vh" }}>
73
+ <DragbleEditor
74
+ ref={editorRef}
75
+ editorKey="your-editor-key"
76
+ editorMode="email"
77
+ minHeight="600px"
78
+ onReady={(editor) => console.log("Editor ready!")}
79
+ onChange={handleChange}
80
+ onError={(error) => console.error("Editor error:", error)}
81
+ />
82
+ </div>
83
+ );
84
+ }
85
+ ```
86
+
87
+ ## Complete Example
88
+
89
+ ```tsx
90
+ import { useRef, useState, useCallback } from "react";
91
+ import {
92
+ DragbleEditor,
93
+ DragbleEditorRef,
94
+ DesignJson,
95
+ } from "dragble-react-editor";
96
+
97
+ function AdvancedEmailBuilder() {
98
+ const editorRef = useRef<DragbleEditorRef>(null);
99
+ const [isDirty, setIsDirty] = useState(false);
100
+
101
+ const handleReady = useCallback((editor) => {
102
+ // Set merge tags (must pass a MergeTagsConfig object)
103
+ editor.setMergeTags({
104
+ customMergeTags: [
105
+ { name: "First Name", value: "{{first_name}}" },
106
+ { name: "Last Name", value: "{{last_name}}" },
107
+ { name: "Company", value: "{{company}}" },
108
+ ],
109
+ excludeDefaults: false,
110
+ sort: true,
111
+ });
112
+
113
+ // Set custom fonts
114
+ editor.setFonts({
115
+ showDefaultFonts: true,
116
+ customFonts: [{ label: "Brand Font", value: "BrandFont, sans-serif" }],
117
+ });
118
+
119
+ // Load saved design if available
120
+ const savedDesign = localStorage.getItem("email-design");
121
+ if (savedDesign) {
122
+ editor.loadDesign(JSON.parse(savedDesign));
123
+ }
124
+ }, []);
125
+
126
+ const handleChange = useCallback(
127
+ (data: { design: DesignJson; type: string }) => {
128
+ setIsDirty(true);
129
+ localStorage.setItem("email-design", JSON.stringify(data.design));
130
+ },
131
+ [],
132
+ );
133
+
134
+ const handleExportHtml = async () => {
135
+ const editor = editorRef.current?.editor;
136
+ if (!editor) return;
137
+
138
+ const html = await editor.exportHtml();
139
+ const blob = new Blob([html], { type: "text/html" });
140
+ const url = URL.createObjectURL(blob);
141
+ const a = document.createElement("a");
142
+ a.href = url;
143
+ a.download = "email.html";
144
+ a.click();
145
+ };
146
+
147
+ const handleExportImage = async () => {
148
+ const editor = editorRef.current?.editor;
149
+ if (!editor) return;
150
+
151
+ const data = await editor.exportImage();
152
+ window.open(data.url, "_blank");
153
+ };
154
+
155
+ return (
156
+ <div style={{ height: "100vh", display: "flex", flexDirection: "column" }}>
157
+ <div
158
+ style={{
159
+ padding: 12,
160
+ borderBottom: "1px solid #ddd",
161
+ display: "flex",
162
+ gap: 8,
163
+ }}
164
+ >
165
+ <button onClick={() => editorRef.current?.editor?.undo()}>Undo</button>
166
+ <button onClick={() => editorRef.current?.editor?.redo()}>Redo</button>
167
+ <button
168
+ onClick={() => editorRef.current?.editor?.showPreview("desktop")}
169
+ >
170
+ Preview
171
+ </button>
172
+ <button onClick={handleExportHtml}>Export HTML</button>
173
+ <button onClick={handleExportImage}>Export Image</button>
174
+ {isDirty && <span style={{ color: "orange" }}>Unsaved changes</span>}
175
+ </div>
176
+
177
+ <DragbleEditor
178
+ ref={editorRef}
179
+ editorKey="your-editor-key"
180
+ editorMode="email"
181
+ height="100%"
182
+ designMode="live"
183
+ options={{
184
+ appearance: { theme: "light" },
185
+ features: {
186
+ preview: true,
187
+ undoRedo: true,
188
+ imageEditor: true,
189
+ },
190
+ }}
191
+ onReady={handleReady}
192
+ onChange={handleChange}
193
+ onError={(error) => console.error(error.message)}
194
+ />
195
+ </div>
196
+ );
197
+ }
198
+
199
+ export default AdvancedEmailBuilder;
200
+ ```
201
+
202
+ ## Props
203
+
204
+ | Prop | Type | Required | Default | Description |
205
+ | --------------- | --------------------------------------------------------------------------- | -------- | ----------- | ---------------------------------------------------------- |
206
+ | `editorKey` | `string` | Yes | — | Editor key for authentication |
207
+ | `design` | `DesignJson \| ModuleData \| null` | No | `undefined` | Initial design to load |
208
+ | `editorMode` | `EditorMode` | No | — | `"email"` \| `"web"` \| `"popup"` |
209
+ | `contentType` | `"module"` | No | — | Single-row module editor mode |
210
+ | `options` | `EditorOptions` | No | `{}` | All editor configuration |
211
+ | `popup` | `PopupConfig` | No | — | Popup config (only when `editorMode` is `"popup"`) |
212
+ | `collaboration` | `boolean \| CollaborationFeaturesConfig` | No | — | Collaboration features |
213
+ | `user` | `UserInfo` | No | — | User info for session/collaboration |
214
+ | `designMode` | `"edit" \| "live"` | No | `"live"` | Template permissions mode |
215
+ | `height` | `string \| number` | No | — | Editor height |
216
+ | `minHeight` | `string \| number` | No | `"600px"` | Minimum editor height |
217
+ | `callbacks` | `Omit<DragbleCallbacks, "onReady" \| "onLoad" \| "onChange" \| "onError">` | No | — | SDK callbacks (excluding those handled by dedicated props) |
218
+ | `className` | `string` | No | — | CSS class for the outer container |
219
+ | `style` | `React.CSSProperties` | No | — | Inline styles for the outer container |
220
+
221
+ | `onReady` | `(editor: DragbleSDK) => void` | No | — | Called when the editor is ready |
222
+ | `onLoad` | `() => void` | No | — | Called when a design is loaded |
223
+ | `onChange` | `(data: { design: DesignJson; type: string }) => void` | No | — | Called when the design changes |
224
+ | `onError` | `(error: Error) => void` | No | — | Called on error |
225
+ | `onComment` | `(action: CommentAction) => void` | No | — | Called on comment events |
226
+
227
+ ## Ref
228
+
229
+ Use a ref to access the SDK instance:
230
+
231
+ ```tsx
232
+ const editorRef = useRef<DragbleEditorRef>(null);
233
+
234
+ // DragbleEditorRef shape:
235
+ // {
236
+ // editor: DragbleSDK | null;
237
+ // isReady: () => boolean;
238
+ // }
239
+ ```
240
+
241
+ ## Hook API
242
+
243
+ The `useDragbleEditor` hook provides a convenient way to access the editor:
244
+
245
+ ```tsx
246
+ import { DragbleEditor, useDragbleEditor } from "dragble-react-editor";
247
+
248
+ function MyEditor() {
249
+ const { ref, editor, isReady } = useDragbleEditor();
250
+
251
+ return (
252
+ <div>
253
+ <button
254
+ onClick={async () => {
255
+ const html = await editor?.exportHtml();
256
+ console.log(html);
257
+ }}
258
+ disabled={!isReady}
259
+ >
260
+ Export
261
+ </button>
262
+ <DragbleEditor ref={ref} editorKey="your-editor-key" />
263
+ </div>
264
+ );
265
+ }
266
+ ```
267
+
268
+ **Returns:** `{ ref, editor, isReady }` — `ref` is passed to the component, `editor` is the SDK instance (or `null`), and `isReady` is a boolean.
269
+
270
+ ## SDK Methods Reference
271
+
272
+ Access the SDK via `editorRef.current?.editor` or the `editor` value from `useDragbleEditor()`. All export and getter methods return Promises.
273
+
274
+ ### Design
275
+
276
+ ```tsx
277
+ editor.loadDesign(design, options?); // void
278
+ const result = await editor.loadDesignAsync(design, options?);
279
+ // => { success, validRowsCount, invalidRowsCount, errors? }
280
+ editor.loadBlank(options?); // void
281
+ const { html, json } = await editor.getDesign(); // Promise
282
+ ```
283
+
284
+ ### Export
285
+
286
+ All export methods are **Promise-based**. There are no callback overloads.
287
+
288
+ ```tsx
289
+ const html = await editor.exportHtml(options?); // Promise<string>
290
+ const json = await editor.exportJson(); // Promise<DesignJson>
291
+ const text = await editor.exportPlainText(); // Promise<string>
292
+ const imageData = await editor.exportImage(options?); // Promise<ExportImageData>
293
+ const pdfData = await editor.exportPdf(options?); // Promise<ExportPdfData>
294
+ const zipData = await editor.exportZip(options?); // Promise<ExportZipData>
295
+ const values = await editor.getPopupValues(); // Promise<PopupValues | null>
296
+ ```
297
+
298
+ ### Merge Tags
299
+
300
+ `setMergeTags` accepts a `MergeTagsConfig` object, not a plain array.
301
+
302
+ ```tsx
303
+ editor.setMergeTags({
304
+ customMergeTags: [
305
+ { name: "First Name", value: "{{first_name}}" },
306
+ { name: "Company", value: "{{company}}" },
307
+ ],
308
+ excludeDefaults: false,
309
+ sort: true,
310
+ });
311
+ const tags = await editor.getMergeTags(); // Promise<(MergeTag | MergeTagGroup)[]>
312
+ ```
313
+
314
+ ### Special Links
315
+
316
+ `setSpecialLinks` accepts a `SpecialLinksConfig` object.
317
+
318
+ ```tsx
319
+ editor.setSpecialLinks({
320
+ customSpecialLinks: [{ name: "Unsubscribe", href: "{{unsubscribe_url}}" }],
321
+ excludeDefaults: false,
322
+ });
323
+ const links = await editor.getSpecialLinks(); // Promise<(SpecialLink | SpecialLinkGroup)[]>
324
+ ```
325
+
326
+ ### Modules
327
+
328
+ ```tsx
329
+ editor.setModules(modules); // void
330
+ editor.setModulesLoading(loading); // void
331
+ const modules = await editor.getModules(); // Promise<Module[]>
332
+ ```
333
+
334
+ ### Fonts
335
+
336
+ ```tsx
337
+ editor.setFonts(config); // void
338
+ const fonts = await editor.getFonts(); // Promise<FontsConfig>
339
+ ```
340
+
341
+ ### Body Values
342
+
343
+ ```tsx
344
+ editor.setBodyValues({
345
+ backgroundColor: "#f5f5f5",
346
+ contentWidth: "600px",
347
+ });
348
+ const values = await editor.getBodyValues(); // Promise<SetBodyValuesOptions>
349
+ ```
350
+
351
+ ### Editor Configuration
352
+
353
+ ```tsx
354
+ editor.setOptions(options); // void — Partial<EditorOptions>
355
+ editor.setToolsConfig(toolsConfig); // void
356
+ editor.setEditorMode(mode); // void
357
+ editor.setEditorConfig(config); // void
358
+ const config = await editor.getEditorConfig(); // Promise<EditorBehaviorConfig>
359
+ ```
360
+
361
+ ### Locale, Language & Text Direction
362
+
363
+ ```tsx
364
+ editor.setLocale(locale, translations?); // void
365
+ editor.setLanguage(language); // void
366
+ const lang = await editor.getLanguage(); // Promise<Language | null>
367
+ editor.setTextDirection(direction); // void — 'ltr' | 'rtl'
368
+ const dir = await editor.getTextDirection(); // Promise<TextDirection>
369
+ ```
370
+
371
+ ### Appearance
372
+
373
+ ```tsx
374
+ editor.setAppearance(appearance); // void
375
+ ```
376
+
377
+ ### Undo / Redo / Save
378
+
379
+ ```tsx
380
+ editor.undo(); // void
381
+ editor.redo(); // void
382
+ const canUndo = await editor.canUndo(); // Promise<boolean>
383
+ const canRedo = await editor.canRedo(); // Promise<boolean>
384
+ editor.save(); // void
385
+ ```
386
+
387
+ ### Preview
388
+
389
+ ```tsx
390
+ editor.showPreview(device?); // void — 'desktop' | 'tablet' | 'mobile'
391
+ editor.hidePreview(); // void
392
+ ```
393
+
394
+ ### Custom Tools
395
+
396
+ ```tsx
397
+ await editor.registerTool(config); // Promise<void>
398
+ await editor.unregisterTool(toolId); // Promise<void>
399
+ const tools = await editor.getTools(); // Promise<Array<{ id, label, baseToolType }>>
400
+ ```
401
+
402
+ ### Custom Widgets
403
+
404
+ ```tsx
405
+ await editor.createWidget(config); // Promise<void>
406
+ await editor.removeWidget(widgetName); // Promise<void>
407
+ ```
408
+
409
+ ### Collaboration & Comments
410
+
411
+ ```tsx
412
+ editor.showComment(commentId); // void
413
+ editor.openCommentPanel(rowId); // void
414
+ ```
415
+
416
+ ### Tabs & Branding
417
+
418
+ ```tsx
419
+ editor.updateTabs(tabs); // void
420
+ editor.setBrandingColors(config); // void
421
+ editor.registerColumns(cells); // void
422
+ ```
423
+
424
+ ### Display Conditions
425
+
426
+ ```tsx
427
+ editor.setDisplayConditions(config); // void
428
+ ```
429
+
430
+ ### Audit
431
+
432
+ ```tsx
433
+ const result = await editor.audit(options?); // Promise<AuditResult>
434
+ ```
435
+
436
+ ### Asset Management
437
+
438
+ ```tsx
439
+ const { success, url, error } = await editor.uploadImage(file, options?);
440
+ const { assets, total } = await editor.listAssets(options?);
441
+ const { success, error } = await editor.deleteAsset(assetId);
442
+ const folders = await editor.listAssetFolders(parentId?);
443
+ const folder = await editor.createAssetFolder(name, parentId?);
444
+ const info = await editor.getStorageInfo();
445
+ ```
446
+
447
+ ### Status & Lifecycle
448
+
449
+ ```tsx
450
+ editor.isReady(); // boolean
451
+ editor.destroy(); // void
452
+ ```
453
+
454
+ ## Events
455
+
456
+ Subscribe to editor events using `addEventListener`:
457
+
458
+ ```tsx
459
+ const unsubscribe = editor.addEventListener("design:updated", (data) => {
460
+ console.log("Design changed:", data);
461
+ });
462
+
463
+ // Or remove manually
464
+ editor.removeEventListener("design:updated", callback);
465
+ ```
466
+
467
+ ### Available Events
468
+
469
+ | Event | Description |
470
+ | -------------------------- | --------------------------- |
471
+ | `editor:ready` | Editor initialized |
472
+ | `design:loaded` | Design loaded |
473
+ | `design:updated` | Design changed |
474
+ | `design:saved` | Design saved |
475
+ | `row:selected` | Row selected |
476
+ | `row:unselected` | Row unselected |
477
+ | `column:selected` | Column selected |
478
+ | `column:unselected` | Column unselected |
479
+ | `content:selected` | Content block selected |
480
+ | `content:unselected` | Content block unselected |
481
+ | `content:modified` | Content block modified |
482
+ | `content:added` | Content block added |
483
+ | `content:deleted` | Content block deleted |
484
+ | `preview:shown` | Preview opened |
485
+ | `preview:hidden` | Preview closed |
486
+ | `image:uploaded` | Image uploaded successfully |
487
+ | `image:error` | Image upload error |
488
+ | `export:html` | HTML exported |
489
+ | `export:plainText` | Plain text exported |
490
+ | `export:image` | Image exported |
491
+ | `save` | Save triggered |
492
+ | `save:success` | Save succeeded |
493
+ | `save:error` | Save failed |
494
+ | `template:requested` | Template requested |
495
+ | `element:selected` | Element selected |
496
+ | `element:deselected` | Element deselected |
497
+ | `export` | Export triggered |
498
+ | `displayCondition:applied` | Display condition applied |
499
+ | `displayCondition:removed` | Display condition removed |
500
+ | `displayCondition:updated` | Display condition updated |
501
+
502
+ ## TypeScript
503
+
504
+ All SDK types are re-exported from the package:
505
+
506
+ ```tsx
507
+ import type {
508
+ DragbleEditorRef,
509
+ DragbleEditorProps,
510
+ DesignJson,
511
+ EditorOptions,
512
+ MergeTag,
513
+ MergeTagGroup,
514
+ MergeTagsConfig,
515
+ SpecialLink,
516
+ SpecialLinkGroup,
517
+ SpecialLinksConfig,
518
+ FontsConfig,
519
+ EditorMode,
520
+ PopupConfig,
521
+ UserInfo,
522
+ CollaborationFeaturesConfig,
523
+ CommentAction,
524
+ } from "dragble-react-editor";
525
+ ```
526
+
527
+ ## Contributing
528
+
529
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines on how to contribute to this project.
530
+
531
+ ## License
532
+
533
+ [MIT](./LICENSE)
@@ -0,0 +1,116 @@
1
+ import React from 'react';
2
+ import { DragbleSDK, DesignJson, ModuleData, EditorMode, EditorOptions, PopupConfig, CollaborationFeaturesConfig, UserInfo, DragbleCallbacks, CommentAction } from 'dragble-types';
3
+ export * from 'dragble-types';
4
+
5
+ /**
6
+ * @dragble/react-editor
7
+ * React wrapper for the Dragble Editor SDK
8
+ */
9
+
10
+ declare global {
11
+ interface Window {
12
+ dragble?: DragbleSDK;
13
+ createEditor?: () => DragbleSDK;
14
+ }
15
+ }
16
+ interface DragbleEditorRef {
17
+ editor: DragbleSDK | null;
18
+ isReady: () => boolean;
19
+ }
20
+ interface DragbleEditorProps {
21
+ editorKey: string;
22
+ design?: DesignJson | ModuleData | null;
23
+ editorMode?: EditorMode;
24
+ /**
25
+ * Content type for module editing mode.
26
+ * When set to "module", the editor is locked to a single row.
27
+ */
28
+ contentType?: "module";
29
+ /**
30
+ * All editor configuration (appearance, tools, features, AI, storage, etc.).
31
+ * These are placed under `options` in the SDK's DragbleConfig.
32
+ */
33
+ options?: EditorOptions;
34
+ /** Popup builder configuration (only used when editorMode is 'popup') */
35
+ popup?: PopupConfig;
36
+ /**
37
+ * Team collaboration features (commenting, reviewer role, etc.)
38
+ * Can be a simple boolean or detailed configuration object.
39
+ *
40
+ * @example Simple boolean
41
+ * ```tsx
42
+ * <DragbleEditor collaboration={true} />
43
+ * ```
44
+ *
45
+ * @example Reviewer role with mentions
46
+ * ```tsx
47
+ * <DragbleEditor
48
+ * collaboration={{
49
+ * enabled: true,
50
+ * role: 'reviewer',
51
+ * commenting: {
52
+ * mentions: true,
53
+ * getMentions: async (search) => {
54
+ * const res = await fetch(`/api/team?q=${search}`);
55
+ * return await res.json();
56
+ * }
57
+ * },
58
+ * }}
59
+ * onComment={(action) => console.log(action)}
60
+ * />
61
+ * ```
62
+ * @default false
63
+ */
64
+ collaboration?: boolean | CollaborationFeaturesConfig;
65
+ /** User information for session identity and collaboration */
66
+ user?: UserInfo;
67
+ /**
68
+ * Design mode for template permissions.
69
+ * - 'edit': Admin mode - shows "Row Actions" for setting row permissions
70
+ * - 'live': End-user mode - enforces row permissions (selectable, draggable, locked, etc.)
71
+ * @default 'live'
72
+ */
73
+ designMode?: "edit" | "live";
74
+ height?: string | number;
75
+ /**
76
+ * Additional callbacks for the SDK.
77
+ * These are placed under `callbacks` in the SDK's DragbleConfig.
78
+ * Note: onReady, onLoad, onChange, onError are handled via dedicated props.
79
+ */
80
+ callbacks?: Omit<DragbleCallbacks, "onReady" | "onLoad" | "onChange" | "onError">;
81
+ className?: string;
82
+ style?: React.CSSProperties;
83
+ minHeight?: string | number;
84
+ /**
85
+ * Custom SDK URL for loading the Dragble SDK script.
86
+ * @default "https://sdk.dragble.com/latest/dragble-sdk.min.js"
87
+ */
88
+ sdkUrl?: string;
89
+ /**
90
+ * SDK version to load from the Dragble CDN.
91
+ * @default "latest"
92
+ */
93
+ sdkVersion?: string;
94
+ /** Editor version forwarded to the SDK init config. */
95
+ editorVersion?: string;
96
+ /** Editor URL forwarded to the SDK init config. */
97
+ editorUrl?: string;
98
+ onReady?: (editor: DragbleSDK) => void;
99
+ onLoad?: () => void;
100
+ onChange?: (data: {
101
+ design: DesignJson;
102
+ type: string;
103
+ }) => void;
104
+ onError?: (error: Error) => void;
105
+ /** Callback invoked when a comment event occurs (create, edit, delete, resolve, reopen) */
106
+ onComment?: (action: CommentAction) => void;
107
+ }
108
+ declare const DragbleEditor: React.ForwardRefExoticComponent<DragbleEditorProps & React.RefAttributes<DragbleEditorRef>>;
109
+ declare function useDragbleEditor(): {
110
+ ref: React.RefObject<DragbleEditorRef>;
111
+ editor: DragbleSDK | null;
112
+ isReady: boolean;
113
+ };
114
+
115
+ export { DragbleEditor, DragbleEditor as default, useDragbleEditor };
116
+ export type { DragbleEditorProps, DragbleEditorRef };