vue2-bbl-editor 1.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/README.md ADDED
@@ -0,0 +1,1694 @@
1
+ # Vue 2 Premium BBL Editor
2
+
3
+ A production-ready, fully configurable rich text editor for Vue 2.6 applications. Built with Tiptap and designed for professional use with extensive customization options and advanced upload management system.
4
+
5
+ ## ๐Ÿš€ Features
6
+
7
+ - โœ… **Vue 2.6 Compatible** - Full support for Vue 2.6+ applications
8
+ - โœ… **Production Ready** - Thoroughly tested and optimized for production use
9
+ - โœ… **Fully Configurable** - Extensive props for customizing every aspect
10
+ - โœ… **Rich Text Editing** - Complete formatting options (bold, italic, underline, etc.)
11
+ - โœ… **Advanced Media** - Resizable images and videos with upload support
12
+ - โœ… **Smart Tables** - Interactive tables with cell controls and resizing
13
+ - โœ… **Upload Management** - Comprehensive upload system with multiple adapters
14
+ - โœ… **Multiple Themes** - Default, minimal, and dark themes included
15
+ - โœ… **TypeScript Support** - Full TypeScript definitions included
16
+ - โœ… **Accessibility** - WCAG compliant with keyboard navigation
17
+ - โœ… **Auto-save** - Built-in auto-save functionality
18
+ - โœ… **Source Code View** - Toggle between visual and HTML source editing
19
+ - โœ… **External Integration** - Easy integration with existing projects
20
+
21
+ ## ๐Ÿ“ฆ Installation
22
+
23
+ ### NPM Installation
24
+
25
+ ```bash
26
+ npm install vue2-bbl-editor
27
+ ```
28
+
29
+ ### CDN for HTML Output Styling
30
+
31
+ For rendering editor HTML content in external projects (React, Vue, Angular, etc.), use the CDN:
32
+
33
+ ```html
34
+ <!-- Global CDN styles for HTML output rendering -->
35
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue2-bbl-editor/dist/editor-content.css" />
36
+ ```
37
+
38
+ Then wrap your editor HTML content with the `.bbl-html-section` class:
39
+
40
+ ```html
41
+ <div class="bbl-html-section">
42
+ <!-- Your editor HTML content here -->
43
+ </div>
44
+ ```
45
+
46
+ See [External HTML Rendering Guide](EXTERNAL_HTML_RENDERING.md) for detailed usage in different frameworks.
47
+
48
+ ### PREVIEW
49
+
50
+ <img src="https://github.com/kazi-shahin/vue2-bbl-editor/blob/main/public/preview.png?raw=true" style="width: 100%"/>
51
+
52
+ ## ๐ŸŽฏ Quick Start
53
+
54
+ ### Global Registration (Recommended)
55
+
56
+ ```javascript
57
+ import Vue from 'vue'
58
+ import PremiumBblEditor from 'vue2-bbl-editor'
59
+
60
+ // Register globally
61
+ Vue.use(PremiumBblEditor)
62
+
63
+ // Or register with options
64
+ Vue.use(PremiumBblEditor, {
65
+ registerAllComponents: true // Registers all sub-components globally
66
+ })
67
+ ```
68
+
69
+ ### HTML Output with CDN Styling
70
+
71
+ The editor automatically wraps HTML output with the `bbl-html-section` class for CDN styling compatibility:
72
+
73
+ ```javascript
74
+ // HTML output is automatically wrapped
75
+ const htmlContent = this.$refs.editor.getContent()
76
+ // Returns: <div class="bbl-html-section">...your content...</div>
77
+
78
+ // To get unwrapped content
79
+ const unwrappedContent = this.$refs.editor.getContent('html', false)
80
+ // Returns: ...your content...
81
+
82
+ // Control wrapping via prop
83
+ <PremiumBblEditor
84
+ :wrap-with-content-class="false"
85
+ v-model="content"
86
+ />
87
+ ```
88
+
89
+ ### Component Registration
90
+
91
+ ```javascript
92
+ // Composition API version (requires @vue/composition-api)
93
+ import { PremiumBblEditor } from 'vue2-bbl-editor'
94
+
95
+ // Options API version (pure Vue 2)
96
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
97
+
98
+ export default {
99
+ components: {
100
+ PremiumBblEditor,
101
+ // or
102
+ PremiumBblEditorOptionsAPI
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Basic Usage
108
+
109
+ #### Composition API Version
110
+
111
+ ```vue
112
+ <template>
113
+ <div>
114
+ <PremiumBblEditor
115
+ v-model="content"
116
+ placeholder="Start writing your content..."
117
+ @input="handleInput"
118
+ @ready="handleReady"
119
+ />
120
+ </div>
121
+ </template>
122
+
123
+ <script>
124
+ export default {
125
+ data() {
126
+ return {
127
+ content: '<p>Hello World!</p>'
128
+ }
129
+ },
130
+ methods: {
131
+ handleInput(content) {
132
+ console.log('Content updated:', content)
133
+ },
134
+ handleReady(editor) {
135
+ console.log('Editor is ready:', editor)
136
+ }
137
+ }
138
+ }
139
+ </script>
140
+ ```
141
+
142
+ #### Options API Version
143
+
144
+ ```vue
145
+ <template>
146
+ <div>
147
+ <PremiumBblEditorOptionsAPI
148
+ v-model="content"
149
+ placeholder="Start writing your content..."
150
+ @input="handleInput"
151
+ @ready="handleReady"
152
+ />
153
+ </div>
154
+ </template>
155
+
156
+ <script>
157
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
158
+
159
+ export default {
160
+ components: {
161
+ PremiumBblEditorOptionsAPI
162
+ },
163
+ data() {
164
+ return {
165
+ content: '<p>Hello World with Options API!</p>'
166
+ }
167
+ },
168
+ methods: {
169
+ handleInput(content) {
170
+ console.log('Content updated:', content)
171
+ },
172
+ handleReady(editor) {
173
+ console.log('Options API Editor is ready:', editor)
174
+ }
175
+ }
176
+ }
177
+ </script>
178
+ ```
179
+
180
+ ## ๐Ÿ“‹ Complete Component API
181
+
182
+ ### Props
183
+
184
+ #### Content & Basic Configuration
185
+
186
+ | Prop | Type | Default | Description |
187
+ |------|------|---------|-------------|
188
+ | `value` | String | `''` | Editor content (v-model) |
189
+ | `placeholder` | String | `'Start writing...'` | Placeholder text when editor is empty |
190
+ | `editable` | Boolean | `true` | Whether editor content can be modified |
191
+ | `outputFormat` | String | `'html'` | Output format: 'html' or 'json' |
192
+ | `autofocus` | Boolean | `false` | Auto-focus editor on mount |
193
+ | `spellcheck` | Boolean | `true` | Enable browser spellcheck |
194
+
195
+ #### Layout & Appearance
196
+
197
+ | Prop | Type | Default | Description |
198
+ |------|------|---------|-------------|
199
+ | `maxHeight` | String/Number | `null` | Maximum editor height (px or CSS value) |
200
+ | `minHeight` | String/Number | `200` | Minimum editor height (px or CSS value) |
201
+ | `theme` | String | `'default'` | Theme: 'default', 'minimal', 'dark' |
202
+ | `editorClass` | String/Array/Object | `''` | Custom CSS classes for editor container |
203
+ | `toolbarClass` | String/Array/Object | `''` | Custom CSS classes for toolbar |
204
+ | `contentClass` | String/Array/Object | `''` | Custom CSS classes for content area |
205
+
206
+ #### UI Component Visibility
207
+
208
+ | Prop | Type | Default | Description |
209
+ |------|------|---------|-------------|
210
+ | `showToolbar` | Boolean | `true` | Show/hide main toolbar |
211
+ | `showBubbleMenu` | Boolean | `true` | Show/hide text selection bubble menu |
212
+ | `showTableBubbleMenu` | Boolean | `true` | Show/hide table-specific bubble menu |
213
+ | `showImageBubbleMenu` | Boolean | `true` | Show/hide image-specific bubble menu |
214
+ | `showVideoBubbleMenu` | Boolean | `true` | Show/hide video-specific bubble menu |
215
+
216
+ #### Toolbar Configuration
217
+
218
+ | Prop | Type | Default | Description |
219
+ |------|------|---------|-------------|
220
+ | `toolbarConfig` | Object | See below | Configure which toolbar buttons to show |
221
+
222
+ **Default Toolbar Configuration:**
223
+ ```javascript
224
+ {
225
+ // Text formatting
226
+ bold: true,
227
+ italic: true,
228
+ underline: true,
229
+ strike: true,
230
+ code: true,
231
+
232
+ // Text styling
233
+ textColor: true,
234
+ highlight: true,
235
+ fontFamily: true,
236
+ fontSize: true,
237
+
238
+ // Alignment and spacing
239
+ textAlign: true,
240
+ lineHeight: true,
241
+
242
+ // Structure
243
+ headings: true,
244
+ lists: true,
245
+ blockquote: true,
246
+ codeBlock: true,
247
+ horizontalRule: true,
248
+
249
+ // Media
250
+ link: true,
251
+ image: true,
252
+ video: true,
253
+ table: true,
254
+
255
+ // Utilities
256
+ clearFormatting: true,
257
+ sourceCode: true,
258
+ undo: true,
259
+ redo: true
260
+ }
261
+ ```
262
+
263
+ #### Extension Configuration
264
+
265
+ | Prop | Type | Default | Description |
266
+ |------|------|---------|-------------|
267
+ | `extensionConfig` | Object | See below | Configure extension behavior |
268
+
269
+ **Default Extension Configuration:**
270
+ ```javascript
271
+ {
272
+ image: {
273
+ allowResize: true,
274
+ allowAlignment: true,
275
+ allowDelete: true,
276
+ maxWidth: '100%',
277
+ quality: 0.8
278
+ },
279
+ video: {
280
+ allowResize: true,
281
+ allowAlignment: true,
282
+ allowDelete: true,
283
+ maxWidth: '100%',
284
+ autoplay: false
285
+ },
286
+ table: {
287
+ resizable: true,
288
+ allowRowControls: true,
289
+ allowColumnControls: true,
290
+ cellSelection: true
291
+ },
292
+ link: {
293
+ openOnClick: false,
294
+ autolink: true,
295
+ linkOnPaste: true
296
+ },
297
+ textAlign: {
298
+ types: ['heading', 'paragraph']
299
+ }
300
+ }
301
+ ```
302
+
303
+ #### Upload & Media Handling
304
+
305
+ | Prop | Type | Default | Description |
306
+ |------|------|---------|-------------|
307
+ | `uploadHandler` | Function | `null` | Custom upload handler function |
308
+ | `imageUploadUrl` | String | `null` | URL endpoint for image uploads |
309
+ | `videoUploadUrl` | String | `null` | URL endpoint for video uploads |
310
+ | `maxFileSize` | Number | `10485760` | Maximum file size in bytes (10MB) |
311
+ | `allowedImageTypes` | Array | `['image/jpeg', 'image/png', 'image/gif', 'image/webp']` | Allowed image MIME types |
312
+ | `allowedVideoTypes` | Array | `['video/mp4', 'video/webm', 'video/ogg']` | Allowed video MIME types |
313
+
314
+ #### Local File Base64 Management
315
+
316
+ | Prop | Type | Default | Description |
317
+ |------|------|---------|-------------|
318
+ | `useBase64Upload` | Boolean | `false` | Force base64 conversion even when upload URLs are provided |
319
+ | `base64Quality` | Number | `0.8` | Image compression quality (0.1 - 1.0) |
320
+ | `base64MaxWidth` | Number | `1920` | Maximum width for compressed images (px) |
321
+ | `base64MaxHeight` | Number | `1080` | Maximum height for compressed images (px) |
322
+ | `enableImageCompression` | Boolean | `true` | Enable automatic image compression |
323
+ | `preserveOriginalFileName` | Boolean | `true` | Preserve original file names in alt text |
324
+ | `base64Prefix` | String | `'data:'` | Custom prefix for base64 data URLs |
325
+
326
+ #### Content Restrictions
327
+
328
+ | Prop | Type | Default | Description |
329
+ |------|------|---------|-------------|
330
+ | `maxContentLength` | Number | `null` | Maximum content length in characters |
331
+ | `allowedHeadings` | Array | `[1, 2, 3, 4, 5, 6]` | Allowed heading levels |
332
+
333
+ #### Styling Options
334
+
335
+ | Prop | Type | Default | Description |
336
+ |------|------|---------|-------------|
337
+ | `fontFamilies` | Array | See below | Available font families |
338
+ | `fontSizes` | Array | See below | Available font sizes |
339
+ | `lineHeights` | Array | See below | Available line heights |
340
+
341
+ **Default Font Options:**
342
+ ```javascript
343
+ // Font Families
344
+ ['Inter', 'Arial', 'Helvetica', 'Times New Roman', 'Georgia', 'Courier New', 'Monaco', 'Menlo']
345
+
346
+ // Font Sizes
347
+ ['12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px']
348
+
349
+ // Line Heights
350
+ ['1', '1.2', '1.4', '1.6', '1.8', '2', '2.5', '3']
351
+ ```
352
+
353
+ #### Auto-save Configuration
354
+
355
+ | Prop | Type | Default | Description |
356
+ |------|------|---------|-------------|
357
+ | `autoSave` | Boolean | `false` | Enable automatic content saving |
358
+ | `autoSaveInterval` | Number | `30000` | Auto-save interval in milliseconds |
359
+
360
+ ### Events
361
+
362
+ | Event | Payload | Description |
363
+ |-------|---------|-------------|
364
+ | `input` | `content: string` | Emitted when content changes (v-model) |
365
+ | `update` | `content: string` | Emitted when content updates |
366
+ | `ready` | `editor: Editor` | Emitted when editor is ready for use |
367
+ | `created` | `editor: Editor` | Emitted when editor instance is created |
368
+ | `focus` | - | Emitted when editor gains focus |
369
+ | `blur` | - | Emitted when editor loses focus |
370
+ | `destroyed` | - | Emitted when editor is destroyed |
371
+ | `auto-save` | `content: string` | Emitted during auto-save |
372
+ | `content-limit-exceeded` | `{current: number, max: number}` | Emitted when content exceeds limit |
373
+ | `image-compressed` | `{originalSize: number, compressedSize: number, originalDimensions: object, compressedDimensions: object, compressionRatio: number}` | Emitted when image is compressed |
374
+ | `error` | `{type: string, message: string, ...}` | Emitted when errors occur |
375
+
376
+ ### Methods
377
+
378
+ Access editor methods via template ref:
379
+
380
+ ```vue
381
+ <template>
382
+ <PremiumBblEditor
383
+ ref="editor"
384
+ v-model="content"
385
+ />
386
+ </template>
387
+
388
+ <script>
389
+ export default {
390
+ methods: {
391
+ focusEditor() {
392
+ this.$refs.editor.focus()
393
+ },
394
+ getContent() {
395
+ return this.$refs.editor.getContent()
396
+ },
397
+ setContent(content) {
398
+ this.$refs.editor.setContent(content)
399
+ },
400
+ executeCommand(command, options) {
401
+ this.$refs.editor.executeCommand(command, options)
402
+ }
403
+ }
404
+ }
405
+ </script>
406
+ ```
407
+
408
+ **Available Methods:**
409
+ - `focus()` - Focus the editor
410
+ - `blur()` - Blur the editor
411
+ - `getContent(format?)` - Get editor content ('html' or 'json')
412
+ - `setContent(content, emitUpdate?)` - Set editor content
413
+ - `executeCommand(command, options?)` - Execute editor command
414
+
415
+ ## ๐Ÿ’ก Usage Examples
416
+
417
+ ### 1. Basic Editor
418
+
419
+ #### Composition API Version
420
+ ```vue
421
+ <template>
422
+ <PremiumBblEditor
423
+ v-model="content"
424
+ placeholder="Start writing..."
425
+ @input="handleInput"
426
+ @ready="handleReady"
427
+ />
428
+ </template>
429
+
430
+ <script>
431
+ export default {
432
+ data() {
433
+ return {
434
+ content: '<p>Hello World!</p>'
435
+ }
436
+ },
437
+ methods: {
438
+ handleInput(content) {
439
+ console.log('Content updated:', content)
440
+ },
441
+ handleReady(editor) {
442
+ console.log('Editor is ready:', editor)
443
+ }
444
+ }
445
+ }
446
+ </script>
447
+ ```
448
+
449
+ #### Options API Version
450
+ ```vue
451
+ <template>
452
+ <PremiumBblEditorOptionsAPI
453
+ v-model="content"
454
+ placeholder="Start writing..."
455
+ @input="handleInput"
456
+ @ready="handleReady"
457
+ />
458
+ </template>
459
+
460
+ <script>
461
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
462
+
463
+ export default {
464
+ components: {
465
+ PremiumBblEditorOptionsAPI
466
+ },
467
+ data() {
468
+ return {
469
+ content: '<p>Hello World with Options API!</p>'
470
+ }
471
+ },
472
+ methods: {
473
+ handleInput(content) {
474
+ console.log('Content updated:', content)
475
+ },
476
+ handleReady(editor) {
477
+ console.log('Options API Editor is ready:', editor)
478
+ }
479
+ }
480
+ }
481
+ </script>
482
+ ```
483
+
484
+ ### 2. Minimal Configuration
485
+
486
+ #### Composition API Version
487
+ ```vue
488
+ <template>
489
+ <PremiumBblEditor
490
+ v-model="content"
491
+ theme="minimal"
492
+ :toolbar-config="{
493
+ bold: true,
494
+ italic: true,
495
+ underline: true,
496
+ link: true,
497
+ lists: true,
498
+ undo: true,
499
+ redo: true
500
+ }"
501
+ placeholder="Minimal editor..."
502
+ />
503
+ </template>
504
+ ```
505
+
506
+ #### Options API Version
507
+ ```vue
508
+ <template>
509
+ <PremiumBblEditorOptionsAPI
510
+ v-model="content"
511
+ theme="minimal"
512
+ :toolbar-config="minimalToolbarConfig"
513
+ placeholder="Minimal editor with Options API..."
514
+ />
515
+ </template>
516
+
517
+ <script>
518
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
519
+
520
+ export default {
521
+ components: {
522
+ PremiumBblEditorOptionsAPI
523
+ },
524
+ data() {
525
+ return {
526
+ content: '<p>This is a minimal editor with limited features.</p>',
527
+ minimalToolbarConfig: {
528
+ bold: true,
529
+ italic: true,
530
+ underline: true,
531
+ link: true,
532
+ lists: true,
533
+ undo: true,
534
+ redo: true
535
+ }
536
+ }
537
+ }
538
+ }
539
+ </script>
540
+ ```
541
+
542
+ ### 3. Advanced Configuration with Upload
543
+
544
+ #### Composition API Version
545
+ ```vue
546
+ <template>
547
+ <PremiumBblEditor
548
+ v-model="content"
549
+ :max-height="400"
550
+ :auto-save="true"
551
+ :auto-save-interval="15000"
552
+ :upload-handler="customUploadHandler"
553
+ :font-families="['Inter', 'Arial', 'Georgia']"
554
+ :extension-config="{
555
+ image: {
556
+ allowResize: true,
557
+ maxWidth: '800px'
558
+ },
559
+ table: {
560
+ resizable: true,
561
+ cellSelection: true
562
+ }
563
+ }"
564
+ @auto-save="handleAutoSave"
565
+ @ready="handleReady"
566
+ />
567
+ </template>
568
+
569
+ <script>
570
+ export default {
571
+ data() {
572
+ return {
573
+ content: '<h2>Advanced Editor</h2><p>With custom upload handling...</p>'
574
+ }
575
+ },
576
+ methods: {
577
+ async customUploadHandler(file) {
578
+ const formData = new FormData()
579
+ formData.append('file', file)
580
+
581
+ const response = await fetch('/api/upload', {
582
+ method: 'POST',
583
+ body: formData
584
+ })
585
+
586
+ const data = await response.json()
587
+ return { src: data.url, alt: file.name }
588
+ },
589
+
590
+ handleAutoSave(content) {
591
+ // Save to your backend
592
+ this.saveToServer(content)
593
+ },
594
+
595
+ handleReady(editor) {
596
+ console.log('Editor ready with advanced features')
597
+ }
598
+ }
599
+ }
600
+ </script>
601
+ ```
602
+
603
+ #### Options API Version
604
+ ```vue
605
+ <template>
606
+ <PremiumBblEditorOptionsAPI
607
+ v-model="content"
608
+ :max-height="maxHeight"
609
+ :auto-save="autoSave"
610
+ :auto-save-interval="autoSaveInterval"
611
+ :upload-handler="customUploadHandler"
612
+ :font-families="fontFamilies"
613
+ :extension-config="extensionConfig"
614
+ @auto-save="handleAutoSave"
615
+ @ready="handleReady"
616
+ />
617
+ </template>
618
+
619
+ <script>
620
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
621
+
622
+ export default {
623
+ components: {
624
+ PremiumBblEditorOptionsAPI
625
+ },
626
+ data() {
627
+ return {
628
+ content: '<h2>Advanced Options API Editor</h2><p>With comprehensive configuration...</p>',
629
+ maxHeight: 400,
630
+ autoSave: true,
631
+ autoSaveInterval: 15000,
632
+ fontFamilies: ['Inter', 'Arial', 'Georgia'],
633
+ extensionConfig: {
634
+ image: {
635
+ allowResize: true,
636
+ maxWidth: '800px',
637
+ quality: 0.9
638
+ },
639
+ table: {
640
+ resizable: true,
641
+ cellSelection: true,
642
+ allowRowControls: true
643
+ },
644
+ link: {
645
+ autolink: true,
646
+ linkOnPaste: true
647
+ }
648
+ }
649
+ }
650
+ },
651
+ methods: {
652
+ async customUploadHandler(file) {
653
+ try {
654
+ const formData = new FormData()
655
+ formData.append('file', file)
656
+
657
+ const response = await fetch('/api/upload', {
658
+ method: 'POST',
659
+ headers: {
660
+ 'Authorization': `Bearer ${this.getAuthToken()}`
661
+ },
662
+ body: formData
663
+ })
664
+
665
+ if (!response.ok) {
666
+ throw new Error(`Upload failed: ${response.statusText}`)
667
+ }
668
+
669
+ const data = await response.json()
670
+ return {
671
+ src: data.url,
672
+ alt: file.name,
673
+ width: data.width,
674
+ height: data.height
675
+ }
676
+ } catch (error) {
677
+ console.error('Upload error:', error)
678
+ throw error
679
+ }
680
+ },
681
+
682
+ handleAutoSave(content) {
683
+ console.log('Auto-saving content...')
684
+ this.saveToServer(content)
685
+ },
686
+
687
+ handleReady(editor) {
688
+ console.log('Options API Editor ready with advanced features')
689
+ // Store editor reference for later use
690
+ this.editor = editor
691
+ },
692
+
693
+ async saveToServer(content) {
694
+ try {
695
+ await fetch('/api/save', {
696
+ method: 'POST',
697
+ headers: {
698
+ 'Content-Type': 'application/json',
699
+ 'Authorization': `Bearer ${this.getAuthToken()}`
700
+ },
701
+ body: JSON.stringify({ content })
702
+ })
703
+ console.log('Content saved successfully')
704
+ } catch (error) {
705
+ console.error('Save failed:', error)
706
+ }
707
+ },
708
+
709
+ getAuthToken() {
710
+ return localStorage.getItem('authToken') || ''
711
+ }
712
+ }
713
+ }
714
+ </script>
715
+ ```
716
+
717
+ ### 4. Read-only Display
718
+
719
+ #### Composition API Version
720
+ ```vue
721
+ <template>
722
+ <PremiumBblEditor
723
+ v-model="content"
724
+ :editable="false"
725
+ :show-toolbar="false"
726
+ :show-bubble-menu="false"
727
+ />
728
+ </template>
729
+
730
+ <script>
731
+ export default {
732
+ data() {
733
+ return {
734
+ content: `
735
+ <h3>Read-only Content</h3>
736
+ <p>This content is displayed in <strong>read-only mode</strong>.</p>
737
+ <blockquote>
738
+ <p>Perfect for displaying formatted content without editing capabilities.</p>
739
+ </blockquote>
740
+ `
741
+ }
742
+ }
743
+ }
744
+ </script>
745
+ ```
746
+
747
+ #### Options API Version
748
+ ```vue
749
+ <template>
750
+ <PremiumBblEditorOptionsAPI
751
+ v-model="content"
752
+ :editable="editable"
753
+ :show-toolbar="showToolbar"
754
+ :show-bubble-menu="showBubbleMenu"
755
+ :show-table-bubble-menu="showTableBubbleMenu"
756
+ :show-image-bubble-menu="showImageBubbleMenu"
757
+ :show-video-bubble-menu="showVideoBubbleMenu"
758
+ />
759
+ </template>
760
+
761
+ <script>
762
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
763
+
764
+ export default {
765
+ components: {
766
+ PremiumBblEditorOptionsAPI
767
+ },
768
+ data() {
769
+ return {
770
+ content: `
771
+ <h3>Read-only Content (Options API)</h3>
772
+ <p>This content is displayed in <strong>read-only mode</strong> using Options API.</p>
773
+ <blockquote>
774
+ <p>Perfect for displaying formatted content without editing capabilities.</p>
775
+ </blockquote>
776
+ <ul>
777
+ <li>No toolbar visible</li>
778
+ <li>No bubble menus</li>
779
+ <li>Content cannot be modified</li>
780
+ </ul>
781
+ `,
782
+ editable: false,
783
+ showToolbar: false,
784
+ showBubbleMenu: false,
785
+ showTableBubbleMenu: false,
786
+ showImageBubbleMenu: false,
787
+ showVideoBubbleMenu: false
788
+ }
789
+ }
790
+ }
791
+ </script>
792
+ ```
793
+
794
+ ### 5. Custom Styling & Dark Theme
795
+
796
+ #### Composition API Version
797
+ ```vue
798
+ <template>
799
+ <PremiumBblEditor
800
+ v-model="content"
801
+ theme="dark"
802
+ editor-class="custom-editor"
803
+ toolbar-class="custom-toolbar"
804
+ content-class="custom-content"
805
+ placeholder="Dark themed editor..."
806
+ />
807
+ </template>
808
+
809
+ <style>
810
+ .custom-editor {
811
+ border-radius: 12px;
812
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
813
+ }
814
+
815
+ .custom-toolbar {
816
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
817
+ }
818
+
819
+ .custom-content {
820
+ font-family: 'Georgia', serif;
821
+ }
822
+ </style>
823
+ ```
824
+
825
+ #### Options API Version
826
+ ```vue
827
+ <template>
828
+ <PremiumBblEditorOptionsAPI
829
+ v-model="content"
830
+ :theme="theme"
831
+ :editor-class="editorClass"
832
+ :toolbar-class="toolbarClass"
833
+ :content-class="contentClass"
834
+ :placeholder="placeholder"
835
+ />
836
+ </template>
837
+
838
+ <script>
839
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
840
+
841
+ export default {
842
+ components: {
843
+ PremiumBblEditorOptionsAPI
844
+ },
845
+ data() {
846
+ return {
847
+ content: '<p>This Options API editor uses custom styling and dark theme.</p>',
848
+ theme: 'dark',
849
+ placeholder: 'Dark themed Options API editor...',
850
+ editorClass: 'custom-editor-options',
851
+ toolbarClass: 'custom-toolbar-options',
852
+ contentClass: 'custom-content-options'
853
+ }
854
+ }
855
+ }
856
+ </script>
857
+
858
+ <style scoped>
859
+ .custom-editor-options {
860
+ border-radius: 12px;
861
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
862
+ border: 2px solid #4f46e5;
863
+ }
864
+
865
+ .custom-toolbar-options {
866
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
867
+ border-bottom: 1px solid #4f46e5;
868
+ }
869
+
870
+ .custom-content-options {
871
+ font-family: 'Georgia', serif;
872
+ line-height: 1.8;
873
+ }
874
+ </style>
875
+ ```
876
+
877
+ ### 6. Local Base64 File Management
878
+
879
+ #### Composition API Version
880
+ ```vue
881
+ <template>
882
+ <PremiumBblEditor
883
+ v-model="content"
884
+ :use-base64-upload="true"
885
+ :enable-image-compression="true"
886
+ :base64-quality="0.8"
887
+ :base64-max-width="1920"
888
+ :base64-max-height="1080"
889
+ :preserve-original-file-name="true"
890
+ placeholder="Upload images for local base64 conversion..."
891
+ @image-compressed="handleImageCompressed"
892
+ @ready="handleReady"
893
+ />
894
+ </template>
895
+
896
+ <script>
897
+ export default {
898
+ data() {
899
+ return {
900
+ content: '<p>Upload images to see base64 conversion with compression!</p>'
901
+ }
902
+ },
903
+ methods: {
904
+ handleImageCompressed(compressionData) {
905
+ console.log('Image compressed:', {
906
+ originalSize: compressionData.originalSize,
907
+ compressedSize: compressionData.compressedSize,
908
+ compressionRatio: compressionData.compressionRatio,
909
+ savings: Math.round(((compressionData.originalSize - compressionData.compressedSize) / compressionData.originalSize) * 100) + '%'
910
+ })
911
+ },
912
+
913
+ handleReady(editor) {
914
+ console.log('Editor ready with base64 management')
915
+ }
916
+ }
917
+ }
918
+ </script>
919
+ ```
920
+
921
+ #### Options API Version
922
+ ```vue
923
+ <template>
924
+ <PremiumBblEditorOptionsAPI
925
+ v-model="content"
926
+ :use-base64-upload="useBase64"
927
+ :enable-image-compression="enableCompression"
928
+ :base64-quality="quality"
929
+ :base64-max-width="maxWidth"
930
+ :base64-max-height="maxHeight"
931
+ :preserve-original-file-name="preserveNames"
932
+ placeholder="Options API with base64 management..."
933
+ @image-compressed="onImageCompressed"
934
+ @ready="onEditorReady"
935
+ />
936
+ </template>
937
+
938
+ <script>
939
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
940
+
941
+ export default {
942
+ components: {
943
+ PremiumBblEditorOptionsAPI
944
+ },
945
+ data() {
946
+ return {
947
+ content: '<p>Options API editor with base64 file management!</p>',
948
+ useBase64: true,
949
+ enableCompression: true,
950
+ quality: 0.8,
951
+ maxWidth: 1920,
952
+ maxHeight: 1080,
953
+ preserveNames: true
954
+ }
955
+ },
956
+ methods: {
957
+ onImageCompressed(data) {
958
+ console.log('Options API - Image compressed:', data)
959
+
960
+ // Show compression statistics
961
+ this.showCompressionStats(data)
962
+ },
963
+
964
+ onEditorReady(editor) {
965
+ console.log('Options API Editor ready with base64 management')
966
+ this.editorInstance = editor
967
+ },
968
+
969
+ showCompressionStats(data) {
970
+ const savings = Math.round(((data.originalSize - data.compressedSize) / data.originalSize) * 100)
971
+ alert(`Image compressed successfully!\nOriginal: ${this.formatFileSize(data.originalSize)}\nCompressed: ${this.formatFileSize(data.compressedSize)}\nSavings: ${savings}%`)
972
+ },
973
+
974
+ formatFileSize(bytes) {
975
+ if (bytes === 0) return '0 Bytes'
976
+ const k = 1024
977
+ const sizes = ['Bytes', 'KB', 'MB', 'GB']
978
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
979
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
980
+ }
981
+ }
982
+ }
983
+ </script>
984
+ ```
985
+
986
+ ### 7. Event Handling & Method Access
987
+
988
+ #### Composition API Version
989
+ ```vue
990
+ <template>
991
+ <div>
992
+ <PremiumBblEditor
993
+ ref="editor"
994
+ v-model="content"
995
+ @input="handleInput"
996
+ @focus="handleFocus"
997
+ @blur="handleBlur"
998
+ @ready="handleReady"
999
+ @auto-save="handleAutoSave"
1000
+ @content-limit-exceeded="handleLimitExceeded"
1001
+ />
1002
+
1003
+ <div class="editor-controls">
1004
+ <button @click="focusEditor">Focus Editor</button>
1005
+ <button @click="getEditorContent">Get Content</button>
1006
+ <button @click="setEditorContent">Set Content</button>
1007
+ <button @click="executeCustomCommand">Bold Text</button>
1008
+ </div>
1009
+ </div>
1010
+ </template>
1011
+
1012
+ <script>
1013
+ export default {
1014
+ data() {
1015
+ return {
1016
+ content: '<p>Editor with comprehensive event handling...</p>'
1017
+ }
1018
+ },
1019
+ methods: {
1020
+ handleInput(content) {
1021
+ console.log('Content changed:', content.length, 'characters')
1022
+ },
1023
+
1024
+ handleFocus() {
1025
+ console.log('Editor focused')
1026
+ },
1027
+
1028
+ handleBlur() {
1029
+ console.log('Editor blurred')
1030
+ },
1031
+
1032
+ handleReady(editor) {
1033
+ console.log('Editor ready:', editor)
1034
+ },
1035
+
1036
+ handleAutoSave(content) {
1037
+ console.log('Auto-saving content...')
1038
+ // Save to backend
1039
+ },
1040
+
1041
+ handleLimitExceeded({ current, max }) {
1042
+ alert(`Content limit exceeded: ${current}/${max} characters`)
1043
+ },
1044
+
1045
+ // Method examples
1046
+ focusEditor() {
1047
+ this.$refs.editor.focus()
1048
+ },
1049
+
1050
+ getEditorContent() {
1051
+ const content = this.$refs.editor.getContent()
1052
+ console.log('Current content:', content)
1053
+ },
1054
+
1055
+ setEditorContent() {
1056
+ this.$refs.editor.setContent('<p>New content set programmatically!</p>')
1057
+ },
1058
+
1059
+ executeCustomCommand() {
1060
+ this.$refs.editor.executeCommand('toggleBold')
1061
+ }
1062
+ }
1063
+ }
1064
+ </script>
1065
+ ```
1066
+
1067
+ #### Options API Version
1068
+ ```vue
1069
+ <template>
1070
+ <div>
1071
+ <PremiumBblEditorOptionsAPI
1072
+ ref="editorOptionsAPI"
1073
+ v-model="content"
1074
+ :max-content-length="maxContentLength"
1075
+ :auto-save="autoSave"
1076
+ :auto-save-interval="autoSaveInterval"
1077
+ @input="handleInput"
1078
+ @focus="handleFocus"
1079
+ @blur="handleBlur"
1080
+ @ready="handleReady"
1081
+ @auto-save="handleAutoSave"
1082
+ @content-limit-exceeded="handleLimitExceeded"
1083
+ @error="handleError"
1084
+ />
1085
+
1086
+ <div class="editor-controls">
1087
+ <button @click="focusEditor">Focus Editor</button>
1088
+ <button @click="blurEditor">Blur Editor</button>
1089
+ <button @click="getEditorContent">Get Content</button>
1090
+ <button @click="setEditorContent">Set Content</button>
1091
+ <button @click="executeCustomCommand">Toggle Bold</button>
1092
+ <button @click="checkActiveState">Check Bold State</button>
1093
+ <button @click="clearContent">Clear Content</button>
1094
+ </div>
1095
+
1096
+ <div class="editor-status" v-if="editorStatus">
1097
+ <h4>Editor Status</h4>
1098
+ <p>Content Length: {{ contentLength }}</p>
1099
+ <p>Is Bold Active: {{ isBoldActive }}</p>
1100
+ <p>Last Action: {{ lastAction }}</p>
1101
+ </div>
1102
+ </div>
1103
+ </template>
1104
+
1105
+ <script>
1106
+ import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
1107
+
1108
+ export default {
1109
+ components: {
1110
+ PremiumBblEditorOptionsAPI
1111
+ },
1112
+ data() {
1113
+ return {
1114
+ content: '<p>Options API Editor with comprehensive event handling and method access...</p>',
1115
+ maxContentLength: 5000,
1116
+ autoSave: true,
1117
+ autoSaveInterval: 20000,
1118
+ editorInstance: null,
1119
+ editorStatus: true,
1120
+ contentLength: 0,
1121
+ isBoldActive: false,
1122
+ lastAction: 'None'
1123
+ }
1124
+ },
1125
+ methods: {
1126
+ handleInput(content) {
1127
+ this.contentLength = content.length
1128
+ this.lastAction = 'Content changed'
1129
+ console.log('Options API - Content changed:', content.length, 'characters')
1130
+ },
1131
+
1132
+ handleFocus() {
1133
+ this.lastAction = 'Editor focused'
1134
+ console.log('Options API - Editor focused')
1135
+ },
1136
+
1137
+ handleBlur() {
1138
+ this.lastAction = 'Editor blurred'
1139
+ console.log('Options API - Editor blurred')
1140
+ },
1141
+
1142
+ handleReady(editor) {
1143
+ this.editorInstance = editor
1144
+ this.lastAction = 'Editor ready'
1145
+ console.log('Options API - Editor ready:', editor)
1146
+ },
1147
+
1148
+ handleAutoSave(content) {
1149
+ this.lastAction = 'Auto-saved'
1150
+ console.log('Options API - Auto-saving content...')
1151
+ this.saveToServer(content)
1152
+ },
1153
+
1154
+ handleLimitExceeded({ current, max }) {
1155
+ this.lastAction = `Content limit exceeded: ${current}/${max}`
1156
+ alert(`Content limit exceeded: ${current}/${max} characters`)
1157
+ },
1158
+
1159
+ handleError(error) {
1160
+ this.lastAction = `Error: ${error.type}`
1161
+ console.error('Options API - Editor error:', error)
1162
+ },
1163
+
1164
+ // Method examples using the Options API component
1165
+ focusEditor() {
1166
+ this.$refs.editorOptionsAPI.focus()
1167
+ this.lastAction = 'Focus method called'
1168
+ },
1169
+
1170
+ blurEditor() {
1171
+ this.$refs.editorOptionsAPI.blur()
1172
+ this.lastAction = 'Blur method called'
1173
+ },
1174
+
1175
+ getEditorContent() {
1176
+ const htmlContent = this.$refs.editorOptionsAPI.getContent('html')
1177
+ const jsonContent = this.$refs.editorOptionsAPI.getContent('json')
1178
+
1179
+ console.log('HTML Content:', htmlContent)
1180
+ console.log('JSON Content:', jsonContent)
1181
+ this.lastAction = 'Get content method called'
1182
+ },
1183
+
1184
+ setEditorContent() {
1185
+ const newContent = `
1186
+ <h3>New Content Set Programmatically</h3>
1187
+ <p>This content was set using the <strong>setContent</strong> method in Options API.</p>
1188
+ <ul>
1189
+ <li>Method called at: ${new Date().toLocaleTimeString()}</li>
1190
+ <li>Using Options API component</li>
1191
+ </ul>
1192
+ `
1193
+ this.$refs.editorOptionsAPI.setContent(newContent)
1194
+ this.lastAction = 'Set content method called'
1195
+ },
1196
+
1197
+ executeCustomCommand() {
1198
+ this.$refs.editorOptionsAPI.executeCommand('toggleBold')
1199
+ this.checkActiveState()
1200
+ this.lastAction = 'Toggle bold command executed'
1201
+ },
1202
+
1203
+ checkActiveState() {
1204
+ this.isBoldActive = this.$refs.editorOptionsAPI.isActive('bold')
1205
+ this.lastAction = 'Checked bold active state'
1206
+ },
1207
+
1208
+ clearContent() {
1209
+ this.$refs.editorOptionsAPI.setContent('<p></p>')
1210
+ this.lastAction = 'Content cleared'
1211
+ },
1212
+
1213
+ async saveToServer(content) {
1214
+ try {
1215
+ // Simulate API call
1216
+ await new Promise(resolve => setTimeout(resolve, 1000))
1217
+ console.log('Options API - Content saved to server')
1218
+ } catch (error) {
1219
+ console.error('Options API - Save failed:', error)
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+ </script>
1225
+
1226
+ <style scoped>
1227
+ .editor-controls {
1228
+ margin: 20px 0;
1229
+ display: flex;
1230
+ gap: 10px;
1231
+ flex-wrap: wrap;
1232
+ }
1233
+
1234
+ .editor-controls button {
1235
+ padding: 8px 16px;
1236
+ background: #3b82f6;
1237
+ color: white;
1238
+ border: none;
1239
+ border-radius: 4px;
1240
+ cursor: pointer;
1241
+ font-size: 14px;
1242
+ }
1243
+
1244
+ .editor-controls button:hover {
1245
+ background: #2563eb;
1246
+ }
1247
+
1248
+ .editor-status {
1249
+ margin-top: 20px;
1250
+ padding: 15px;
1251
+ background: #f8f9fa;
1252
+ border: 1px solid #dee2e6;
1253
+ border-radius: 6px;
1254
+ }
1255
+
1256
+ .editor-status h4 {
1257
+ margin-top: 0;
1258
+ color: #495057;
1259
+ }
1260
+
1261
+ .editor-status p {
1262
+ margin: 5px 0;
1263
+ font-size: 14px;
1264
+ color: #6c757d;
1265
+ }
1266
+ </style>
1267
+ ```
1268
+
1269
+ ## ๐Ÿ”Œ Upload System Integration
1270
+
1271
+ The editor includes a comprehensive upload management system for handling file uploads with multiple adapters.
1272
+
1273
+ ### Basic Upload Setup
1274
+
1275
+ ```vue
1276
+ <template>
1277
+ <PremiumBblEditor
1278
+ v-model="content"
1279
+ @ready="onEditorReady"
1280
+ />
1281
+ </template>
1282
+
1283
+ <script>
1284
+ import {
1285
+ UploadManager,
1286
+ LocalStorageAdapter,
1287
+ integrateTipTapUpload,
1288
+ createUploadConfig
1289
+ } from 'vue2-bbl-editor'
1290
+
1291
+ export default {
1292
+ data() {
1293
+ return {
1294
+ content: '<p>Try uploading images...</p>',
1295
+ uploadManager: null
1296
+ }
1297
+ },
1298
+
1299
+ async created() {
1300
+ // Create upload configuration
1301
+ const config = createUploadConfig('localStorage', {
1302
+ validation: {
1303
+ maxSize: 5 * 1024 * 1024, // 5MB
1304
+ allowedTypes: ['image/jpeg', 'image/png', 'image/gif']
1305
+ }
1306
+ })
1307
+
1308
+ // Initialize upload manager
1309
+ this.uploadManager = new UploadManager(config)
1310
+
1311
+ // Register local storage adapter
1312
+ const adapter = new LocalStorageAdapter()
1313
+ this.uploadManager.registerAdapter(adapter)
1314
+ this.uploadManager.setDefaultAdapter('local-storage')
1315
+ },
1316
+
1317
+ methods: {
1318
+ onEditorReady(editor) {
1319
+ // Integrate upload system with editor
1320
+ integrateTipTapUpload(editor, this.uploadManager, {
1321
+ onStart: () => console.log('Upload started'),
1322
+ onEnd: () => console.log('Upload finished')
1323
+ })
1324
+ }
1325
+ }
1326
+ }
1327
+ </script>
1328
+ ```
1329
+
1330
+ ### Custom Upload Adapter
1331
+
1332
+ ```javascript
1333
+ // Create custom adapter for your API
1334
+ class CustomApiAdapter {
1335
+ constructor(options) {
1336
+ this.name = 'custom-api'
1337
+ this.apiUrl = options.apiUrl
1338
+ this.headers = options.headers || {}
1339
+ }
1340
+
1341
+ async upload(file, options) {
1342
+ const formData = new FormData()
1343
+ formData.append('file', file)
1344
+
1345
+ const response = await fetch(this.apiUrl, {
1346
+ method: 'POST',
1347
+ headers: this.headers,
1348
+ body: formData
1349
+ })
1350
+
1351
+ if (!response.ok) {
1352
+ throw new Error(`Upload failed: ${response.statusText}`)
1353
+ }
1354
+
1355
+ const result = await response.json()
1356
+ return {
1357
+ url: result.url,
1358
+ size: file.size,
1359
+ metadata: {
1360
+ fileName: file.name,
1361
+ fileType: file.type
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+
1367
+ // Register and use
1368
+ const adapter = new CustomApiAdapter({
1369
+ apiUrl: '/api/upload',
1370
+ headers: { 'Authorization': 'Bearer your-token' }
1371
+ })
1372
+ uploadManager.registerAdapter(adapter)
1373
+ uploadManager.setDefaultAdapter('custom-api')
1374
+ ```
1375
+
1376
+ ### Upload Event Handling
1377
+
1378
+ ```javascript
1379
+ // Listen to upload events
1380
+ uploadManager.on('progress', (progress) => {
1381
+ console.log(`Upload progress: ${progress.percentage}%`)
1382
+ })
1383
+
1384
+ uploadManager.on('uploadCompleted', (event) => {
1385
+ console.log('Upload completed:', event.result.url)
1386
+ })
1387
+
1388
+ uploadManager.on('uploadFailed', (event) => {
1389
+ console.error('Upload failed:', event.error.message)
1390
+ })
1391
+ ```
1392
+
1393
+ ## ๐Ÿงฉ Individual Component Usage
1394
+
1395
+ Import and use individual components for custom implementations:
1396
+
1397
+ ```javascript
1398
+ import {
1399
+ PremiumBblEditor,
1400
+ PremiumBblEditorOptionsAPI,
1401
+ ToolbarMain,
1402
+ ToolbarGroup,
1403
+ ToolbarButton,
1404
+ EditorBubbleMenu,
1405
+ TableBubbleMenu,
1406
+ ImageBubbleMenu,
1407
+ VideoBubbleMenu,
1408
+ ImageModal,
1409
+ VideoModal,
1410
+ LinkModal,
1411
+ DiagnosticTool,
1412
+ DebugHelper,
1413
+ useEditor
1414
+ } from 'vue2-bbl-editor'
1415
+ ```
1416
+
1417
+ ### Available Components
1418
+
1419
+ #### Main Components
1420
+ - `PremiumBblEditor` - Main editor component (Composition API)
1421
+ - `PremiumBblEditorOptionsAPI` - Main editor component (Options API)
1422
+ - `DiagnosticTool` - Built-in diagnostic and troubleshooting tool
1423
+ - `DebugHelper` - Development debugging helper
1424
+
1425
+ #### Toolbar Components
1426
+ - `ToolbarMain` - Complete toolbar component
1427
+ - `ToolbarGroup` - Toolbar button group container
1428
+ - `ToolbarButton` - Individual toolbar button
1429
+
1430
+ #### Menu Components
1431
+ - `EditorBubbleMenu` - Text selection bubble menu
1432
+ - `TableBubbleMenu` - Table-specific bubble menu
1433
+ - `ImageBubbleMenu` - Image-specific bubble menu
1434
+ - `VideoBubbleMenu` - Video-specific bubble menu
1435
+
1436
+ #### Modal Components
1437
+ - `ImageModal` - Image upload and configuration modal
1438
+ - `VideoModal` - Video upload and configuration modal
1439
+ - `LinkModal` - Link creation and editing modal
1440
+
1441
+ #### Composables
1442
+ - `useEditor` - Core editor composable for custom implementations
1443
+
1444
+ ### Custom Implementation Example
1445
+
1446
+ ```vue
1447
+ <template>
1448
+ <div class="custom-editor">
1449
+ <ToolbarMain
1450
+ v-if="editor"
1451
+ :editor="editor"
1452
+ :config="toolbarConfig"
1453
+ @execute-command="executeCommand"
1454
+ />
1455
+
1456
+ <div class="editor-content">
1457
+ <editor-content :editor="editor" />
1458
+ </div>
1459
+
1460
+ <EditorBubbleMenu
1461
+ v-if="editor"
1462
+ :editor="editor"
1463
+ :config="toolbarConfig"
1464
+ />
1465
+ </div>
1466
+ </template>
1467
+
1468
+ <script>
1469
+ import { EditorContent } from '@tiptap/vue-2'
1470
+ import { ToolbarMain, EditorBubbleMenu, useEditor } from 'vue2-bbl-editor'
1471
+
1472
+ export default {
1473
+ components: {
1474
+ EditorContent,
1475
+ ToolbarMain,
1476
+ EditorBubbleMenu
1477
+ },
1478
+
1479
+ setup() {
1480
+ const { editor, executeCommand } = useEditor({
1481
+ content: '<p>Custom editor implementation</p>',
1482
+ extensions: [
1483
+ // Your custom extensions
1484
+ ]
1485
+ })
1486
+
1487
+ return {
1488
+ editor,
1489
+ executeCommand,
1490
+ toolbarConfig: {
1491
+ bold: true,
1492
+ italic: true,
1493
+ underline: true
1494
+ }
1495
+ }
1496
+ }
1497
+ }
1498
+ </script>
1499
+ ```
1500
+
1501
+ ## ๐Ÿ”Œ Extensions & Customization
1502
+
1503
+ The package includes custom extensions that enhance the editing experience:
1504
+
1505
+ ### Available Extensions
1506
+ - `ResizableImage` - Enhanced image handling with resize controls
1507
+ - `ResizableVideo` - Video embedding with resize functionality
1508
+ - `CustomTableCell` - Enhanced table cell with controls
1509
+ - `CustomTableHeader` - Enhanced table header with controls
1510
+
1511
+ ### Using Extensions Directly
1512
+
1513
+ ```javascript
1514
+ import { ResizableImage, ResizableVideo } from 'vue2-bbl-editor'
1515
+ import { Editor } from '@tiptap/vue-2'
1516
+
1517
+ const editor = new Editor({
1518
+ extensions: [
1519
+ ResizableImage.configure({
1520
+ allowResize: true,
1521
+ allowAlignment: true,
1522
+ maxWidth: '800px'
1523
+ }),
1524
+ ResizableVideo.configure({
1525
+ allowResize: true,
1526
+ autoplay: false
1527
+ })
1528
+ ]
1529
+ })
1530
+ ```
1531
+
1532
+ ## ๐ŸŒ External Project Integration
1533
+
1534
+ For detailed integration instructions for external projects, see our [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md).
1535
+
1536
+ ### Quick Integration
1537
+
1538
+ ```bash
1539
+ # Install in your existing project
1540
+ npm install vue2-bbl-editor
1541
+
1542
+ # Install required dependencies
1543
+ npm install @vue/composition-api @tiptap/core @tiptap/vue-2 @tiptap/starter-kit
1544
+ ```
1545
+
1546
+ ```vue
1547
+ <template>
1548
+ <PremiumBblEditor
1549
+ v-model="content"
1550
+ @ready="onEditorReady"
1551
+ />
1552
+ </template>
1553
+
1554
+ <script>
1555
+ import { PremiumBblEditor } from 'vue2-bbl-editor'
1556
+
1557
+ export default {
1558
+ components: { PremiumBblEditor },
1559
+ data() {
1560
+ return {
1561
+ content: '<p>Start editing...</p>'
1562
+ }
1563
+ },
1564
+ methods: {
1565
+ onEditorReady(editor) {
1566
+ console.log('Editor ready in external project!')
1567
+ }
1568
+ }
1569
+ }
1570
+ </script>
1571
+ ```
1572
+
1573
+ ## ๐Ÿงช Development & Testing
1574
+
1575
+ ```bash
1576
+ # Install dependencies
1577
+ npm install
1578
+
1579
+ # Run development server
1580
+ npm run serve
1581
+
1582
+ # Build library
1583
+ npm run build:lib
1584
+
1585
+ # Run tests
1586
+ npm test
1587
+
1588
+ # Lint code
1589
+ npm run lint
1590
+ ```
1591
+
1592
+ ### Development Tools
1593
+
1594
+ The package includes built-in development and diagnostic tools:
1595
+
1596
+ ```vue
1597
+ <template>
1598
+ <div>
1599
+ <!-- Your editor -->
1600
+ <PremiumBblEditor v-model="content" />
1601
+
1602
+ <!-- Development tools -->
1603
+ <DiagnosticTool v-if="isDevelopment" />
1604
+ <DebugHelper v-if="isDevelopment" />
1605
+ </div>
1606
+ </template>
1607
+
1608
+ <script>
1609
+ import { PremiumBblEditor, DiagnosticTool, DebugHelper } from 'vue2-bbl-editor'
1610
+
1611
+ export default {
1612
+ components: {
1613
+ PremiumBblEditor,
1614
+ DiagnosticTool,
1615
+ DebugHelper
1616
+ },
1617
+ computed: {
1618
+ isDevelopment() {
1619
+ return process.env.NODE_ENV === 'development'
1620
+ }
1621
+ }
1622
+ }
1623
+ </script>
1624
+ ```
1625
+
1626
+ ## ๐Ÿ”ง Troubleshooting
1627
+
1628
+ ### Common Issues
1629
+
1630
+ 1. **Editor not loading**: Check if all required dependencies are installed
1631
+ 2. **Upload not working**: Verify upload handler configuration
1632
+ 3. **Styling issues**: Ensure CSS is properly imported
1633
+ 4. **TypeScript errors**: Check type definitions import
1634
+
1635
+ ### Diagnostic Tools
1636
+
1637
+ Use the built-in diagnostic tool to identify issues:
1638
+
1639
+ ```vue
1640
+ <template>
1641
+ <div>
1642
+ <PremiumBblEditor v-model="content" />
1643
+ <DiagnosticTool />
1644
+ </div>
1645
+ </template>
1646
+ ```
1647
+
1648
+ ### Debug Mode
1649
+
1650
+ Enable debug mode for detailed logging:
1651
+
1652
+ ```vue
1653
+ <template>
1654
+ <PremiumBblEditor
1655
+ v-model="content"
1656
+ :debug="true"
1657
+ />
1658
+ </template>
1659
+ ```
1660
+
1661
+ For more troubleshooting help, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).
1662
+
1663
+ ## ๐Ÿ“š Documentation
1664
+
1665
+ - [Installation Guide](INSTALLATION.md)
1666
+ - [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md)
1667
+ - [Upload System Documentation](src/upload/README.md)
1668
+ - [Troubleshooting Guide](TROUBLESHOOTING.md)
1669
+ - [API Reference](types/index.d.ts)
1670
+ - [Examples](examples/)
1671
+
1672
+ ## ๐Ÿ“„ License
1673
+
1674
+ MIT License - see [LICENSE](LICENSE) file for details.
1675
+
1676
+ ## ๐Ÿค Contributing
1677
+
1678
+ 1. Fork the repository
1679
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
1680
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
1681
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
1682
+ 5. Open a Pull Request
1683
+
1684
+ ## ๐Ÿ“ž Support
1685
+
1686
+ - ๐Ÿ“ง Email: support@example.com
1687
+ - ๐Ÿ› Issues: [GitHub Issues](https://github.com/Mahadi74/vue2-bbl-editor/issues)
1688
+ - ๐Ÿ“– Documentation: [Full Documentation](https://github.com/Mahadi74/vue2-bbl-editor/wiki)
1689
+
1690
+ ## ๐Ÿ™ Acknowledgments
1691
+
1692
+ - [Tiptap](https://tiptap.dev/) - The headless editor framework
1693
+ - [ProseMirror](https://prosemirror.net/) - The foundation
1694
+ - [Vue.js](https://vuejs.org/) - The progressive framework