dragble-vue-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/dist/index.js ADDED
@@ -0,0 +1,741 @@
1
+ import { defineComponent, h, ref, computed, onMounted, onUnmounted, watch } from 'vue';
2
+
3
+ /**
4
+ * Dragble Editor Vue 3 Component
5
+ *
6
+ * A Vue 3 wrapper for the Dragble Editor SDK.
7
+ */
8
+ const SDK_CDN_URL = "https://sdk.dragble.com/latest/dragble-sdk.min.js";
9
+ // Map of URL -> Promise for caching SDK loads per URL
10
+ const sdkLoadPromises = new Map();
11
+ /**
12
+ * Get the SDK URL to use.
13
+ * @param customUrl - Optional custom SDK URL override
14
+ * @param sdkVersion - Optional SDK version to load
15
+ * @returns The SDK URL to load
16
+ */
17
+ function getSDKUrl(customUrl, sdkVersion) {
18
+ if (customUrl && sdkVersion !== undefined) {
19
+ console.warn("[DragbleEditor] sdkVersion is ignored when sdkUrl is provided.");
20
+ }
21
+ return customUrl ?? `https://sdk.dragble.com/${sdkVersion ?? "latest"}/dragble-sdk.min.js`;
22
+ }
23
+ /**
24
+ * Create an SDK module from the global dragble object.
25
+ */
26
+ function createSDKModuleFromGlobal() {
27
+ return {
28
+ dragble: window.dragble,
29
+ createEditor: (config) => {
30
+ const instance = new window.dragble.constructor();
31
+ instance.init(config);
32
+ return instance;
33
+ },
34
+ DragbleSDK: window.dragble.constructor,
35
+ };
36
+ }
37
+ /**
38
+ * Load the SDK from a URL.
39
+ * Supports custom SDK URLs for enterprise self-hosted or specific versions.
40
+ * @param customUrl - Optional custom SDK URL
41
+ */
42
+ function loadSDK(customUrl) {
43
+ const sdkUrl = getSDKUrl(customUrl);
44
+ // Check cache for this specific URL
45
+ const cachedPromise = sdkLoadPromises.get(sdkUrl);
46
+ if (cachedPromise)
47
+ return cachedPromise;
48
+ // Check if already loaded globally (only for default URL to avoid conflicts)
49
+ if (sdkUrl === SDK_CDN_URL && typeof window !== "undefined" && window.dragble) {
50
+ return Promise.resolve(createSDKModuleFromGlobal());
51
+ }
52
+ return loadSDKScript(sdkUrl);
53
+ }
54
+ /**
55
+ * Load the SDK script from a specific URL.
56
+ * Each unique URL is cached separately to support multiple SDK sources.
57
+ * @param sdkUrl - The SDK URL to load
58
+ */
59
+ function loadSDKScript(sdkUrl) {
60
+ // Check cache for this specific URL
61
+ const cachedPromise = sdkLoadPromises.get(sdkUrl);
62
+ if (cachedPromise)
63
+ return cachedPromise;
64
+ const loadPromise = new Promise((resolve, reject) => {
65
+ const script = document.createElement("script");
66
+ script.src = sdkUrl;
67
+ script.async = true;
68
+ script.onload = () => {
69
+ if (window.dragble) {
70
+ // Resolve with SDK module interface
71
+ resolve(createSDKModuleFromGlobal());
72
+ }
73
+ else {
74
+ sdkLoadPromises.delete(sdkUrl);
75
+ reject(new Error("Failed to load Dragble SDK - createEditor not found"));
76
+ }
77
+ };
78
+ script.onerror = () => {
79
+ sdkLoadPromises.delete(sdkUrl);
80
+ reject(new Error(`Failed to load Dragble SDK from ${sdkUrl}`));
81
+ };
82
+ document.head.appendChild(script);
83
+ });
84
+ // Cache the promise for this URL
85
+ sdkLoadPromises.set(sdkUrl, loadPromise);
86
+ return loadPromise;
87
+ }
88
+ // ============================================================================
89
+ // Component
90
+ // ============================================================================
91
+ /**
92
+ * DragbleEditor Vue 3 Component
93
+ *
94
+ * @example
95
+ * ```vue
96
+ * <template>
97
+ * <DragbleEditor
98
+ * ref="editorRef"
99
+ * editor-key="your-editor-key"
100
+ * editor-mode="email"
101
+ * @ready="onReady"
102
+ * @change="onChange"
103
+ * />
104
+ * </template>
105
+ *
106
+ * <script setup lang="ts">
107
+ * import { ref } from 'vue';
108
+ * import { DragbleEditor } from '@dragble/vue-editor';
109
+ *
110
+ * const editorRef = ref<InstanceType<typeof DragbleEditor>>();
111
+ *
112
+ * const onReady = (editor) => console.log('Ready!', editor);
113
+ * const onChange = (data) => console.log('Changed:', data);
114
+ *
115
+ * const handleSave = () => {
116
+ * editorRef.value?.saveDesign((design) => {
117
+ * console.log('Design:', design);
118
+ * });
119
+ * };
120
+ * </script>
121
+ * ```
122
+ */
123
+ const DragbleEditor = defineComponent({
124
+ name: "DragbleEditor",
125
+ props: {
126
+ /** Editor key for authentication (required) */
127
+ editorKey: {
128
+ type: String,
129
+ required: true,
130
+ },
131
+ /** Initial design to load */
132
+ design: {
133
+ type: Object,
134
+ default: undefined,
135
+ },
136
+ /** Editor mode (email, web, popup) */
137
+ editorMode: {
138
+ type: String,
139
+ default: "email",
140
+ },
141
+ /** Popup builder configuration (only used when editorMode is 'popup') */
142
+ popup: {
143
+ type: Object,
144
+ default: undefined,
145
+ },
146
+ /** Content type: 'module' for single-row module editor */
147
+ contentType: {
148
+ type: String,
149
+ default: undefined,
150
+ },
151
+ /** AI features configuration */
152
+ ai: {
153
+ type: Object,
154
+ default: undefined,
155
+ },
156
+ /** UI language/locale */
157
+ locale: {
158
+ type: String,
159
+ default: undefined,
160
+ },
161
+ /**
162
+ * Custom translation overrides keyed by locale code.
163
+ * Each locale maps translation keys to translated strings,
164
+ * allowing partial or full override of the editor's built-in UI strings.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * translations: {
169
+ * 'en-US': { 'toolbar.save': 'Save Draft' },
170
+ * 'fr-FR': { 'toolbar.save': 'Enregistrer le brouillon' },
171
+ * }
172
+ * ```
173
+ */
174
+ translations: {
175
+ type: Object,
176
+ default: undefined,
177
+ },
178
+ /** Text direction (ltr, rtl) */
179
+ textDirection: {
180
+ type: String,
181
+ default: undefined,
182
+ },
183
+ /** Visual customization */
184
+ appearance: {
185
+ type: Object,
186
+ default: undefined,
187
+ },
188
+ /** Enable/disable tools */
189
+ tools: {
190
+ type: Object,
191
+ default: undefined,
192
+ },
193
+ /** Feature toggles */
194
+ features: {
195
+ type: Object,
196
+ default: undefined,
197
+ },
198
+ /** Merge tags for personalization */
199
+ mergeTags: {
200
+ type: Array,
201
+ default: undefined,
202
+ },
203
+ /** Special link categories */
204
+ specialLinks: {
205
+ type: Array,
206
+ default: undefined,
207
+ },
208
+ /** Custom modules */
209
+ modules: {
210
+ type: Array,
211
+ default: undefined,
212
+ },
213
+ /** Display conditions configuration */
214
+ displayConditions: {
215
+ type: Object,
216
+ default: undefined,
217
+ },
218
+ /** Template language for multi-language support */
219
+ language: {
220
+ type: Object,
221
+ default: undefined,
222
+ },
223
+ /** Fonts configuration */
224
+ fonts: {
225
+ type: Object,
226
+ default: undefined,
227
+ },
228
+ /** Custom tools to register (Dragble-style) */
229
+ customTools: {
230
+ type: Array,
231
+ default: undefined,
232
+ },
233
+ /** Default body/canvas values applied on init */
234
+ bodyValues: {
235
+ type: Object,
236
+ default: undefined,
237
+ },
238
+ /** Header row JSON to inject as a locked, non-editable row at the top */
239
+ header: {
240
+ type: Object,
241
+ default: undefined,
242
+ },
243
+ /** Footer row JSON to inject as a locked, non-editable row at the bottom */
244
+ footer: {
245
+ type: Object,
246
+ default: undefined,
247
+ },
248
+ /** Editor behavior configuration */
249
+ editor: {
250
+ type: Object,
251
+ default: undefined,
252
+ },
253
+ /** Custom CSS URLs or inline styles */
254
+ customCSS: {
255
+ type: Array,
256
+ default: undefined,
257
+ },
258
+ /** Custom JS URLs or inline scripts */
259
+ customJS: {
260
+ type: Array,
261
+ default: undefined,
262
+ },
263
+ /** Height of the editor */
264
+ height: {
265
+ type: [String, Number],
266
+ default: "600px",
267
+ },
268
+ /** Minimum height for the editor */
269
+ minHeight: {
270
+ type: [String, Number],
271
+ default: "600px",
272
+ },
273
+ /** Additional editor options (appearance, tools, features, AI, etc.) */
274
+ options: {
275
+ type: Object,
276
+ default: undefined,
277
+ },
278
+ /**
279
+ * SDK callbacks (onModuleSave, onContentDialog, onPreview, onHeaderRowClick, etc.)
280
+ * Note: onReady/onLoad/onChange/onError are handled via Vue emits, not this prop.
281
+ */
282
+ callbacks: {
283
+ type: Object,
284
+ default: undefined,
285
+ },
286
+ /**
287
+ * Custom SDK URL for loading the Dragble SDK script.
288
+ * Use this for enterprise self-hosted SDK or specific versions.
289
+ * @default "https://sdk.dragble.com/latest/dragble-sdk.min.js"
290
+ */
291
+ sdkUrl: {
292
+ type: String,
293
+ default: undefined,
294
+ },
295
+ /**
296
+ * SDK version to load from the Dragble CDN.
297
+ * @default "latest"
298
+ */
299
+ sdkVersion: {
300
+ type: String,
301
+ default: undefined,
302
+ },
303
+ /** Editor version forwarded to the SDK init config. */
304
+ editorVersion: {
305
+ type: String,
306
+ default: undefined,
307
+ },
308
+ /** Editor URL forwarded to the SDK init config. */
309
+ editorUrl: {
310
+ type: String,
311
+ default: undefined,
312
+ },
313
+ /**
314
+ * Team collaboration features (commenting, reviewer role, etc.)
315
+ * Can be a simple boolean or detailed configuration object.
316
+ * Only works with editorMode 'email' or 'web'.
317
+ * @default false
318
+ */
319
+ collaboration: {
320
+ type: [Boolean, Object],
321
+ default: undefined,
322
+ },
323
+ /** User information for session identity and collaboration */
324
+ user: {
325
+ type: Object,
326
+ default: undefined,
327
+ },
328
+ /**
329
+ * Design mode for template permissions.
330
+ * - 'edit': Admin mode - shows "Row Actions" for setting row permissions
331
+ * - 'live': End-user mode - enforces row permissions
332
+ * @default 'live'
333
+ */
334
+ designMode: {
335
+ type: String,
336
+ default: undefined,
337
+ },
338
+ },
339
+ emits: ["ready", "load", "change", "error", "comment"],
340
+ setup(props, { emit, expose }) {
341
+ const containerId = `dragble-editor-${Math.random().toString(36).substr(2, 9)}`;
342
+ const sdkRef = ref(null);
343
+ const isReady = ref(false);
344
+ const hasLoadedSDK = ref(false);
345
+ // Build config from props
346
+ const buildConfig = () => {
347
+ const editorConfig = props.contentType === "module"
348
+ ? {
349
+ ...props.editor,
350
+ contentType: props.contentType,
351
+ minRows: 1,
352
+ maxRows: 1,
353
+ }
354
+ : props.editor;
355
+ // Build collaboration feature config
356
+ let featuresConfig = props.features;
357
+ if (props.collaboration !== undefined) {
358
+ const collaborationConfig = typeof props.collaboration === "object"
359
+ ? {
360
+ ...props.collaboration,
361
+ onComment: (action) => {
362
+ emit("comment", action);
363
+ },
364
+ }
365
+ : props.collaboration;
366
+ featuresConfig = {
367
+ ...featuresConfig,
368
+ collaboration: collaborationConfig,
369
+ };
370
+ }
371
+ // Build callbacks (top-level SDK callbacks)
372
+ const callbacks = {
373
+ ...props.callbacks,
374
+ };
375
+ // Build options (all editor configuration lives here)
376
+ const options = {
377
+ ...props.options,
378
+ ...(props.locale !== undefined && { locale: props.locale }),
379
+ ...(props.translations !== undefined && {
380
+ translations: props.translations,
381
+ }),
382
+ ...(props.textDirection !== undefined && {
383
+ textDirection: props.textDirection,
384
+ }),
385
+ ...(props.language !== undefined && { language: props.language }),
386
+ ...(props.appearance !== undefined && { appearance: props.appearance }),
387
+ ...(props.tools !== undefined && { tools: props.tools }),
388
+ ...(props.customTools !== undefined && {
389
+ customTools: props.customTools,
390
+ }),
391
+ ...(props.fonts !== undefined && { fonts: props.fonts }),
392
+ ...(props.bodyValues !== undefined && { bodyValues: props.bodyValues }),
393
+ ...(props.header !== undefined && { header: props.header }),
394
+ ...(props.footer !== undefined && { footer: props.footer }),
395
+ ...(featuresConfig !== undefined && { features: featuresConfig }),
396
+ ...(props.ai !== undefined && { ai: props.ai }),
397
+ ...(props.mergeTags !== undefined && {
398
+ mergeTags: { customMergeTags: props.mergeTags },
399
+ }),
400
+ ...(props.specialLinks !== undefined && {
401
+ specialLinks: { customSpecialLinks: props.specialLinks },
402
+ }),
403
+ ...(props.modules !== undefined && { modules: props.modules }),
404
+ ...(props.displayConditions !== undefined && {
405
+ displayConditions: props.displayConditions,
406
+ }),
407
+ ...(editorConfig !== undefined && { editor: editorConfig }),
408
+ ...(props.customCSS !== undefined && { customCSS: props.customCSS }),
409
+ ...(props.customJS !== undefined && { customJS: props.customJS }),
410
+ ...(props.user !== undefined && { user: props.user }),
411
+ minHeight: props.minHeight,
412
+ };
413
+ return {
414
+ containerId,
415
+ editorKey: props.editorKey,
416
+ ...(props.design !== undefined && {
417
+ design: props.design,
418
+ }),
419
+ ...(props.editorMode !== undefined && { editorMode: props.editorMode }),
420
+ ...(props.popup !== undefined && { popup: props.popup }),
421
+ ...(props.designMode !== undefined && { designMode: props.designMode }),
422
+ ...(props.editorVersion !== undefined && {
423
+ editorVersion: props.editorVersion,
424
+ }),
425
+ ...(props.editorUrl !== undefined && { editorUrl: props.editorUrl }),
426
+ callbacks,
427
+ options,
428
+ };
429
+ };
430
+ const resolvedSdkUrl = computed(() => getSDKUrl(props.sdkUrl, props.sdkVersion));
431
+ // Initialize SDK
432
+ onMounted(async () => {
433
+ try {
434
+ await loadSDK(resolvedSdkUrl.value);
435
+ hasLoadedSDK.value = true;
436
+ const { createEditor } = await loadSDK(resolvedSdkUrl.value);
437
+ const config = buildConfig();
438
+ const sdk = createEditor(config);
439
+ sdkRef.value = sdk;
440
+ // Set up event listeners
441
+ sdk.addEventListener("editor:ready", () => {
442
+ isReady.value = true;
443
+ emit("ready", sdk);
444
+ });
445
+ sdk.addEventListener("design:loaded", (data) => {
446
+ emit("load", data);
447
+ });
448
+ sdk.addEventListener("design:updated", (data) => {
449
+ emit("change", data);
450
+ });
451
+ }
452
+ catch (err) {
453
+ const error = err instanceof Error ? err : new Error(String(err));
454
+ console.error("Initialization error:", error.message);
455
+ emit("error", error);
456
+ }
457
+ });
458
+ // Cleanup on unmount
459
+ onUnmounted(() => {
460
+ if (sdkRef.value) {
461
+ sdkRef.value.destroy();
462
+ sdkRef.value = null;
463
+ }
464
+ });
465
+ // Watch for design changes
466
+ watch(() => props.design, (newDesign) => {
467
+ if (newDesign && sdkRef.value && isReady.value) {
468
+ sdkRef.value.loadDesign(newDesign);
469
+ }
470
+ });
471
+ // Watch for merge tags changes
472
+ watch(() => props.mergeTags, (newTags) => {
473
+ if (newTags && sdkRef.value && isReady.value) {
474
+ sdkRef.value.setMergeTags({ customMergeTags: newTags });
475
+ }
476
+ });
477
+ // Watch for modules changes
478
+ watch(() => props.modules, (newModules) => {
479
+ if (newModules && sdkRef.value && isReady.value) {
480
+ sdkRef.value.setModules(newModules);
481
+ }
482
+ });
483
+ // Watch for display conditions changes
484
+ watch(() => props.displayConditions, (newConditions) => {
485
+ if (newConditions && sdkRef.value && isReady.value) {
486
+ sdkRef.value.setDisplayConditions(newConditions);
487
+ }
488
+ });
489
+ // ========================================================================
490
+ // Exposed methods - Full SDK pass-through
491
+ // ========================================================================
492
+ // Design methods
493
+ const loadDesign = (design, options) => sdkRef.value?.loadDesign(design, options);
494
+ const loadBlank = () => sdkRef.value?.loadBlank();
495
+ const saveDesign = (callback) => sdkRef.value?.saveDesign(callback);
496
+ const getDesign = () => sdkRef.value?.getDesign();
497
+ // Export methods (async-only)
498
+ const exportHtml = (options) => sdkRef.value?.exportHtml(options);
499
+ const exportPlainText = () => sdkRef.value?.exportPlainText();
500
+ const exportJson = () => sdkRef.value?.exportJson();
501
+ const exportImage = (options) => sdkRef.value?.exportImage(options);
502
+ const exportPdf = (options) => sdkRef.value?.exportPdf(options);
503
+ const exportZip = (options) => sdkRef.value?.exportZip(options);
504
+ // Merge tags
505
+ const setMergeTags = (config) => sdkRef.value?.setMergeTags(config);
506
+ const getMergeTags = () => sdkRef.value?.getMergeTags();
507
+ // Special links
508
+ const setSpecialLinks = (config) => sdkRef.value?.setSpecialLinks(config);
509
+ const getSpecialLinks = () => sdkRef.value?.getSpecialLinks();
510
+ // Modules
511
+ const setModulesLoading = (loading) => sdkRef.value?.setModulesLoading(loading);
512
+ const setModules = (modules) => sdkRef.value?.setModules(modules);
513
+ const getModules = () => sdkRef.value?.getModules();
514
+ // Fonts
515
+ const setFonts = (config) => sdkRef.value?.setFonts(config);
516
+ const getFonts = () => sdkRef.value?.getFonts();
517
+ // Body values
518
+ const setBodyValues = (values) => sdkRef.value?.setBodyValues(values);
519
+ const getBodyValues = () => sdkRef.value?.getBodyValues();
520
+ // Configuration
521
+ const setOptions = (options) => sdkRef.value?.setOptions(options);
522
+ const setToolsConfig = (config) => sdkRef.value?.setToolsConfig(config);
523
+ const setEditorMode = (mode) => sdkRef.value?.setEditorMode(mode);
524
+ const setEditorConfig = (config) => sdkRef.value?.setEditorConfig(config);
525
+ const getEditorConfig = () => sdkRef.value?.getEditorConfig();
526
+ const setLocale = (locale) => sdkRef.value?.setLocale(locale);
527
+ const setTextDirection = (direction) => sdkRef.value?.setTextDirection(direction);
528
+ const setAppearance = (config) => sdkRef.value?.setAppearance(config);
529
+ const setCustomCSS = (css) => sdkRef.value?.setCustomCSS(css);
530
+ const setCustomJS = (js) => sdkRef.value?.setCustomJS(js);
531
+ // Display conditions
532
+ const setDisplayConditions = (config) => sdkRef.value?.setDisplayConditions(config);
533
+ // Undo/Redo
534
+ const undo = () => sdkRef.value?.undo();
535
+ const redo = () => sdkRef.value?.redo();
536
+ const save = () => sdkRef.value?.save();
537
+ // Preview
538
+ const showPreview = (device) => sdkRef.value?.showPreview(device);
539
+ const hidePreview = () => sdkRef.value?.hidePreview();
540
+ // Tools
541
+ const registerTool = (config) => sdkRef.value?.registerTool(config);
542
+ const unregisterTool = (toolId) => sdkRef.value?.unregisterTool(toolId);
543
+ const getTools = () => sdkRef.value?.getTools();
544
+ // Language
545
+ const setLanguage = (language) => sdkRef.value?.setLanguage(language);
546
+ const getLanguage = () => sdkRef.value?.getLanguage();
547
+ // Popup values
548
+ const getPopupValues = () => sdkRef.value?.getPopupValues();
549
+ // Branding
550
+ const setBrandingColors = (config) => sdkRef.value?.setBrandingColors(config);
551
+ // Collaboration
552
+ const showComment = (commentId) => sdkRef.value?.showComment(commentId);
553
+ const openCommentPanel = (rowId) => sdkRef.value?.openCommentPanel(rowId);
554
+ // Custom widgets
555
+ const createWidget = (config) => sdkRef.value?.createWidget(config);
556
+ const removeWidget = (widgetName) => sdkRef.value?.removeWidget(widgetName);
557
+ // Undo/Redo state
558
+ const canUndo = () => sdkRef.value?.canUndo();
559
+ const canRedo = () => sdkRef.value?.canRedo();
560
+ // Tabs
561
+ const updateTabs = (tabs) => sdkRef.value?.updateTabs(tabs);
562
+ // Audit
563
+ const audit = (optionsOrCallback, callback) => {
564
+ if (typeof optionsOrCallback === "function") {
565
+ return sdkRef.value?.audit(optionsOrCallback);
566
+ }
567
+ if (callback) {
568
+ return sdkRef.value?.audit(optionsOrCallback, callback);
569
+ }
570
+ return sdkRef.value?.audit(optionsOrCallback);
571
+ };
572
+ // Events
573
+ const addEventListener = (event, callback) => sdkRef.value?.addEventListener(event, callback);
574
+ const removeEventListener = (event, callback) => sdkRef.value?.removeEventListener(event, callback);
575
+ // Advanced
576
+ const registerColumns = (cells) => sdkRef.value?.registerColumns(cells);
577
+ // Expose methods to parent
578
+ expose({
579
+ // SDK instance
580
+ editor: sdkRef,
581
+ isReady,
582
+ // Design methods
583
+ loadDesign,
584
+ loadBlank,
585
+ saveDesign,
586
+ getDesign,
587
+ // Export methods
588
+ exportHtml,
589
+ exportJson,
590
+ exportPlainText,
591
+ exportImage,
592
+ exportPdf,
593
+ exportZip,
594
+ // Popup values (exported from methods)
595
+ getPopupValues,
596
+ // Merge tags
597
+ setMergeTags,
598
+ getMergeTags,
599
+ // Special links
600
+ setSpecialLinks,
601
+ getSpecialLinks,
602
+ // Modules
603
+ setModulesLoading,
604
+ setModules,
605
+ getModules,
606
+ // Fonts
607
+ setFonts,
608
+ getFonts,
609
+ // Body values
610
+ setBodyValues,
611
+ getBodyValues,
612
+ // Configuration
613
+ setOptions,
614
+ setToolsConfig,
615
+ setEditorMode,
616
+ setEditorConfig,
617
+ getEditorConfig,
618
+ setLocale,
619
+ setTextDirection,
620
+ setAppearance,
621
+ setCustomCSS,
622
+ setCustomJS,
623
+ // Display conditions
624
+ setDisplayConditions,
625
+ // Undo/Redo
626
+ undo,
627
+ redo,
628
+ save,
629
+ // Preview
630
+ showPreview,
631
+ hidePreview,
632
+ // Tools
633
+ registerTool,
634
+ unregisterTool,
635
+ getTools,
636
+ // Language
637
+ setLanguage,
638
+ getLanguage,
639
+ // Branding
640
+ setBrandingColors,
641
+ // Collaboration
642
+ showComment,
643
+ openCommentPanel,
644
+ // Custom widgets
645
+ createWidget,
646
+ removeWidget,
647
+ // Undo/Redo state
648
+ canUndo,
649
+ canRedo,
650
+ // Tabs
651
+ updateTabs,
652
+ // Audit
653
+ audit,
654
+ // Events
655
+ addEventListener,
656
+ removeEventListener,
657
+ // Advanced
658
+ registerColumns,
659
+ });
660
+ return {
661
+ containerId,
662
+ isReady,
663
+ };
664
+ },
665
+ render() {
666
+ const height = typeof this.height === "number" ? `${this.height}px` : this.height;
667
+ return h("div", {
668
+ id: this.containerId,
669
+ style: {
670
+ width: "100%",
671
+ height,
672
+ },
673
+ });
674
+ },
675
+ });
676
+ // ============================================================================
677
+ // Composable
678
+ // ============================================================================
679
+ /**
680
+ * Composable to use the Dragble SDK directly
681
+ *
682
+ * @example
683
+ * ```vue
684
+ * <script setup lang="ts">
685
+ * import { useDragbleEditor } from 'dragble-vue-editor';
686
+ *
687
+ * const { editor, isReady, containerId } = useDragbleEditor({
688
+ * editorKey: 'your-editor-key',
689
+ * editorMode: 'email',
690
+ * });
691
+ *
692
+ * const handleExport = async () => {
693
+ * if (isReady.value && editor.value) {
694
+ * const html = await editor.value.exportHtml();
695
+ * console.log(html);
696
+ * }
697
+ * };
698
+ * </script>
699
+ *
700
+ * <template>
701
+ * <div :id="containerId" style="height: 600px" />
702
+ * <button @click="handleExport" :disabled="!isReady">Export</button>
703
+ * </template>
704
+ * ```
705
+ */
706
+ function useDragbleEditor(config, sdkUrl, sdkVersion) {
707
+ const containerId = `dragble-editor-${Math.random().toString(36).substring(2, 11)}`;
708
+ const editor = ref(null);
709
+ const isReady = ref(false);
710
+ const resolvedSdkUrl = getSDKUrl(sdkUrl, sdkVersion);
711
+ onMounted(async () => {
712
+ try {
713
+ const { createEditor } = await loadSDK(resolvedSdkUrl);
714
+ const sdk = createEditor({
715
+ ...config,
716
+ containerId,
717
+ });
718
+ editor.value = sdk;
719
+ sdk.addEventListener("editor:ready", () => {
720
+ isReady.value = true;
721
+ });
722
+ }
723
+ catch (err) {
724
+ console.error("[useDragbleEditor] Failed to load SDK:", err);
725
+ }
726
+ });
727
+ onUnmounted(() => {
728
+ if (editor.value) {
729
+ editor.value.destroy();
730
+ editor.value = null;
731
+ }
732
+ });
733
+ return {
734
+ editor,
735
+ isReady,
736
+ containerId,
737
+ };
738
+ }
739
+
740
+ export { DragbleEditor, DragbleEditor as default, useDragbleEditor };
741
+ //# sourceMappingURL=index.js.map