# Complete Component Usage Guide

This guide provides comprehensive examples of how to use all components included in the Vue2 Premium BBL Editor package.

## Table of Contents

1. [Main Editor Components](#main-editor-components)
2. [Toolbar Components](#toolbar-components)
3. [Menu Components](#menu-components)
4. [Modal Components](#modal-components)
5. [Upload System Components](#upload-system-components)
6. [Development Tools](#development-tools)
7. [Composables](#composables)
8. [Advanced Usage Patterns](#advanced-usage-patterns)

## Main Editor Components

### PremiumBblEditor (Composition API)

The main editor component using Vue 3 Composition API (compatible with Vue 2.6+ via @vue/composition-api).

**Import:**
```javascript
import { PremiumBblEditor } from 'vue2-premium-bbl-editor'
```

**Basic Usage:**
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    placeholder="Start writing..."
    @ready="handleReady"
  />
</template>
```

### PremiumBblEditorOptionsAPI (Options API)

The same editor component using pure Vue 2 Options API (no Composition API dependency required).

**Import:**
```javascript
import { PremiumBblEditorOptionsAPI } from 'vue2-premium-bbl-editor'
```

**Basic Usage:**
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    placeholder="Start writing with Options API..."
    @ready="handleReady"
  />
</template>
```

### Complete Options API Example

```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :placeholder="placeholder"
    :editable="editable"
    :theme="theme"
    :toolbar-config="toolbarConfig"
    :extension-config="extensionConfig"
    :upload-handler="uploadHandler"
    :auto-save="autoSave"
    :auto-save-interval="autoSaveInterval"
    :max-height="maxHeight"
    :min-height="minHeight"
    :font-families="fontFamilies"
    :font-sizes="fontSizes"
    :line-heights="lineHeights"
    :allowed-headings="allowedHeadings"
    :max-file-size="maxFileSize"
    :allowed-image-types="allowedImageTypes"
    :allowed-video-types="allowedVideoTypes"
    :show-toolbar="showToolbar"
    :show-bubble-menu="showBubbleMenu"
    :show-table-bubble-menu="showTableBubbleMenu"
    :show-image-bubble-menu="showImageBubbleMenu"
    :show-video-bubble-menu="showVideoBubbleMenu"
    :editor-class="editorClass"
    :toolbar-class="toolbarClass"
    :content-class="contentClass"
    @input="handleInput"
    @update="handleUpdate"
    @ready="handleReady"
    @created="handleCreated"
    @focus="handleFocus"
    @blur="handleBlur"
    @destroyed="handleDestroyed"
    @auto-save="handleAutoSave"
    @content-limit-exceeded="handleLimitExceeded"
    @error="handleError"
  />
</template>

<script>
import { PremiumBblEditorOptionsAPI } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  
  data() {
    return {
      content: '<p>Start writing with Options API...</p>',
      placeholder: 'Enter your content here...',
      editable: true,
      theme: 'default', // 'default', 'minimal', 'dark'
      autoSave: true,
      autoSaveInterval: 30000, // 30 seconds
      maxHeight: 500,
      minHeight: 200,
      maxFileSize: 10 * 1024 * 1024, // 10MB
      showToolbar: true,
      showBubbleMenu: true,
      showTableBubbleMenu: true,
      showImageBubbleMenu: true,
      showVideoBubbleMenu: true,
      
      // Toolbar configuration
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true,
        strike: true,
        code: true,
        textColor: true,
        highlight: true,
        fontFamily: true,
        fontSize: true,
        textAlign: true,
        lineHeight: true,
        headings: true,
        lists: true,
        blockquote: true,
        codeBlock: true,
        horizontalRule: true,
        link: true,
        image: true,
        video: true,
        table: true,
        clearFormatting: true,
        sourceCode: true,
        undo: true,
        redo: true
      },
      
      // Extension configuration
      extensionConfig: {
        image: {
          allowResize: true,
          allowAlignment: true,
          allowDelete: true,
          maxWidth: '100%',
          quality: 0.8
        },
        video: {
          allowResize: true,
          allowAlignment: true,
          allowDelete: true,
          maxWidth: '100%',
          autoplay: false
        },
        table: {
          resizable: true,
          allowRowControls: true,
          allowColumnControls: true,
          cellSelection: true
        },
        link: {
          openOnClick: false,
          autolink: true,
          linkOnPaste: true
        }
      },
      
      // Styling options
      fontFamilies: [
        'Inter',
        'Arial',
        'Helvetica',
        'Times New Roman',
        'Georgia',
        'Courier New'
      ],
      fontSizes: [
        '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px'
      ],
      lineHeights: [
        '1', '1.2', '1.4', '1.6', '1.8', '2', '2.5', '3'
      ],
      allowedHeadings: [1, 2, 3, 4, 5, 6],
      allowedImageTypes: [
        'image/jpeg',
        'image/png', 
        'image/gif',
        'image/webp'
      ],
      allowedVideoTypes: [
        'video/mp4',
        'video/webm',
        'video/ogg'
      ],
      
      // Local file base64 management
      useBase64Upload: true,
      base64Quality: 0.8,
      base64MaxWidth: 1920,
      base64MaxHeight: 1080,
      enableImageCompression: true,
      preserveOriginalFileName: true,
      base64Prefix: 'data:',
      
      // CSS classes
      editorClass: 'my-custom-editor-options',
      toolbarClass: 'my-custom-toolbar-options',
      contentClass: 'my-custom-content-options'
    }
  },
  
  methods: {
    // Event handlers
    handleInput(content) {
      console.log('Options API - Content changed:', content)
    },
    
    handleUpdate(content) {
      console.log('Options API - Content updated:', content)
    },
    
    handleReady(editor) {
      console.log('Options API - Editor ready:', editor)
      // Store editor reference for later use
      this.editorInstance = editor
    },
    
    handleCreated(editor) {
      console.log('Options API - Editor created:', editor)
    },
    
    handleFocus() {
      console.log('Options API - Editor focused')
    },
    
    handleBlur() {
      console.log('Options API - Editor blurred')
    },
    
    handleDestroyed() {
      console.log('Options API - Editor destroyed')
    },
    
    handleAutoSave(content) {
      console.log('Options API - Auto-saving content...')
      // Save to your backend
      this.saveToServer(content)
    },
    
    handleLimitExceeded({ current, max }) {
      console.log(`Options API - Content limit exceeded: ${current}/${max}`)
      alert(`Content too long: ${current}/${max} characters`)
    },
    
    handleError(error) {
      console.error('Options API - Editor error:', error)
      // Handle different error types
      switch (error.type) {
        case 'missing-dependencies':
          this.showDependencyError(error.dependencies)
          break
        case 'initialization-failed':
          this.showInitializationError(error.message)
          break
        default:
          this.showGenericError(error.message)
      }
    },
    
    handleImageCompressed(compressionData) {
      console.log('Options API - Image compressed:', compressionData)
      
      // Calculate savings percentage
      const savings = Math.round(((compressionData.originalSize - compressionData.compressedSize) / compressionData.originalSize) * 100)
      
      // Show compression statistics
      console.log(`Compression stats:
        Original: ${this.formatFileSize(compressionData.originalSize)}
        Compressed: ${this.formatFileSize(compressionData.compressedSize)}
        Savings: ${savings}%
        Ratio: ${compressionData.compressionRatio.toFixed(2)}x
        Original dimensions: ${compressionData.originalDimensions.width}×${compressionData.originalDimensions.height}
        Compressed dimensions: ${compressionData.compressedDimensions.width}×${compressionData.compressedDimensions.height}
      `)
      
      // You could emit this data to parent component or store it
      this.$emit('image-compression-stats', compressionData)
    },
    
    // Custom upload handler
    async uploadHandler(file) {
      try {
        const formData = new FormData()
        formData.append('file', file)
        
        const response = await fetch('/api/upload', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.getAuthToken()}`
          },
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`Upload failed: ${response.statusText}`)
        }
        
        const data = await response.json()
        return {
          src: data.url,
          alt: file.name
        }
      } catch (error) {
        console.error('Options API - Upload error:', error)
        throw error
      }
    },
    
    // Helper methods
    async saveToServer(content) {
      try {
        await fetch('/api/save', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.getAuthToken()}`
          },
          body: JSON.stringify({ content })
        })
        console.log('Options API - Content saved successfully')
      } catch (error) {
        console.error('Options API - Save failed:', error)
      }
    },
    
    getAuthToken() {
      return localStorage.getItem('authToken') || ''
    },
    
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes'
      const k = 1024
      const sizes = ['Bytes', 'KB', 'MB', 'GB']
      const i = Math.floor(Math.log(bytes) / Math.log(k))
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
    },
    
    showDependencyError(dependencies) {
      const message = `Missing dependencies: ${dependencies.join(', ')}`
      alert(message)
    },
    
    showInitializationError(message) {
      alert(`Editor initialization failed: ${message}`)
    },
    
    showGenericError(message) {
      alert(`Editor error: ${message}`)
    }
  }
}
</script>

<style scoped>
.my-custom-editor-options {
  border: 2px solid #e2e8f0;
  border-radius: 8px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.my-custom-toolbar-options {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-bottom: 1px solid #e2e8f0;
}

.my-custom-content-options {
  font-family: 'Georgia', serif;
  line-height: 1.6;
}
</style>
```

### Component Comparison

| Feature | PremiumBblEditor (Composition API) | PremiumBblEditorOptionsAPI (Options API) |
|---------|-----------------------------------|------------------------------------------|
| **Vue Version** | Vue 2.6+ with @vue/composition-api | Pure Vue 2.x |
| **Dependencies** | Requires @vue/composition-api | No additional dependencies |
| **Performance** | Slightly better reactivity | Standard Vue 2 reactivity |
| **Bundle Size** | Slightly larger (composition-api) | Smaller bundle |
| **API Style** | Modern Composition API patterns | Traditional Options API |
| **Props** | Identical | Identical |
| **Events** | Identical | Identical |
| **Methods** | Identical | Identical |
| **Features** | All features available | All features available |

### When to Use Which Version

**Use PremiumBblEditor (Composition API) when:**
- You're already using @vue/composition-api in your project
- You prefer modern Vue 3 style code patterns
- You want the latest reactivity improvements
- You're planning to migrate to Vue 3 in the future

**Use PremiumBblEditorOptionsAPI (Options API) when:**
- You want to minimize dependencies
- Your project uses traditional Vue 2 patterns
- You want the smallest possible bundle size
- You're working with legacy Vue 2 projects
- You prefer the familiar Options API syntax

### Shared Props, Events, and Methods

Both components share the exact same interface:

```vue
<template>
  <PremiumBblEditor
    v-model="content"
    :placeholder="placeholder"
    :editable="editable"
    :theme="theme"
    :toolbar-config="toolbarConfig"
    :extension-config="extensionConfig"
    :upload-handler="uploadHandler"
    :auto-save="autoSave"
    :auto-save-interval="autoSaveInterval"
    :max-height="maxHeight"
    :min-height="minHeight"
    :font-families="fontFamilies"
    :font-sizes="fontSizes"
    :line-heights="lineHeights"
    :allowed-headings="allowedHeadings"
    :max-file-size="maxFileSize"
    :allowed-image-types="allowedImageTypes"
    :allowed-video-types="allowedVideoTypes"
    :show-toolbar="showToolbar"
    :show-bubble-menu="showBubbleMenu"
    :show-table-bubble-menu="showTableBubbleMenu"
    :show-image-bubble-menu="showImageBubbleMenu"
    :show-video-bubble-menu="showVideoBubbleMenu"
    :editor-class="editorClass"
    :toolbar-class="toolbarClass"
    :content-class="contentClass"
    @input="handleInput"
    @update="handleUpdate"
    @ready="handleReady"
    @created="handleCreated"
    @focus="handleFocus"
    @blur="handleBlur"
    @destroyed="handleDestroyed"
    @auto-save="handleAutoSave"
    @content-limit-exceeded="handleLimitExceeded"
    @error="handleError"
  />
</template>

<script>
import { PremiumBblEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor
  },
  
  data() {
    return {
      content: '<p>Start writing...</p>',
      placeholder: 'Enter your content here...',
      editable: true,
      theme: 'default', // 'default', 'minimal', 'dark'
      autoSave: true,
      autoSaveInterval: 30000, // 30 seconds
      maxHeight: 500,
      minHeight: 200,
      maxFileSize: 10 * 1024 * 1024, // 10MB
      showToolbar: true,
      showBubbleMenu: true,
      showTableBubbleMenu: true,
      showImageBubbleMenu: true,
      showVideoBubbleMenu: true,
      
      // Toolbar configuration
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true,
        strike: true,
        code: true,
        textColor: true,
        highlight: true,
        fontFamily: true,
        fontSize: true,
        textAlign: true,
        lineHeight: true,
        headings: true,
        lists: true,
        blockquote: true,
        codeBlock: true,
        horizontalRule: true,
        link: true,
        image: true,
        video: true,
        table: true,
        clearFormatting: true,
        sourceCode: true,
        undo: true,
        redo: true
      },
      
      // Extension configuration
      extensionConfig: {
        image: {
          allowResize: true,
          allowAlignment: true,
          allowDelete: true,
          maxWidth: '100%',
          quality: 0.8
        },
        video: {
          allowResize: true,
          allowAlignment: true,
          allowDelete: true,
          maxWidth: '100%',
          autoplay: false
        },
        table: {
          resizable: true,
          allowRowControls: true,
          allowColumnControls: true,
          cellSelection: true
        },
        link: {
          openOnClick: false,
          autolink: true,
          linkOnPaste: true
        }
      },
      
      // Styling options
      fontFamilies: [
        'Inter',
        'Arial',
        'Helvetica',
        'Times New Roman',
        'Georgia',
        'Courier New'
      ],
      fontSizes: [
        '12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px'
      ],
      lineHeights: [
        '1', '1.2', '1.4', '1.6', '1.8', '2', '2.5', '3'
      ],
      allowedHeadings: [1, 2, 3, 4, 5, 6],
      allowedImageTypes: [
        'image/jpeg',
        'image/png', 
        'image/gif',
        'image/webp'
      ],
      allowedVideoTypes: [
        'video/mp4',
        'video/webm',
        'video/ogg'
      ],
      
      // CSS classes
      editorClass: 'my-custom-editor',
      toolbarClass: 'my-custom-toolbar',
      contentClass: 'my-custom-content'
    }
  },
  
  methods: {
    // Event handlers
    handleInput(content) {
      console.log('Content changed:', content)
    },
    
    handleUpdate(content) {
      console.log('Content updated:', content)
    },
    
    handleReady(editor) {
      console.log('Editor ready:', editor)
      // Editor is ready, you can now use editor methods
    },
    
    handleCreated(editor) {
      console.log('Editor created:', editor)
    },
    
    handleFocus() {
      console.log('Editor focused')
    },
    
    handleBlur() {
      console.log('Editor blurred')
    },
    
    handleDestroyed() {
      console.log('Editor destroyed')
    },
    
    handleAutoSave(content) {
      console.log('Auto-saving content...')
      // Save to your backend
      this.saveToServer(content)
    },
    
    handleLimitExceeded({ current, max }) {
      console.log(`Content limit exceeded: ${current}/${max}`)
      alert(`Content too long: ${current}/${max} characters`)
    },
    
    handleError(error) {
      console.error('Editor error:', error)
      // Handle different error types
      switch (error.type) {
        case 'missing-dependencies':
          this.showDependencyError(error.dependencies)
          break
        case 'initialization-failed':
          this.showInitializationError(error.message)
          break
        default:
          this.showGenericError(error.message)
      }
    },
    
    // Custom upload handler
    async uploadHandler(file) {
      try {
        const formData = new FormData()
        formData.append('file', file)
        
        const response = await fetch('/api/upload', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.authToken}`
          },
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`Upload failed: ${response.statusText}`)
        }
        
        const data = await response.json()
        return {
          src: data.url,
          alt: file.name
        }
      } catch (error) {
        console.error('Upload error:', error)
        throw error
      }
    },
    
    // Helper methods
    async saveToServer(content) {
      try {
        await fetch('/api/save', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${this.authToken}`
          },
          body: JSON.stringify({ content })
        })
        console.log('Content saved successfully')
      } catch (error) {
        console.error('Save failed:', error)
      }
    },
    
    showDependencyError(dependencies) {
      const message = `Missing dependencies: ${dependencies.join(', ')}`
      alert(message)
    },
    
    showInitializationError(message) {
      alert(`Editor initialization failed: ${message}`)
    },
    
    showGenericError(message) {
      alert(`Editor error: ${message}`)
    }
  }
}
</script>

<style scoped>
.my-custom-editor {
  border: 2px solid #e2e8f0;
  border-radius: 8px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.my-custom-toolbar {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-bottom: 1px solid #e2e8f0;
}

.my-custom-content {
  font-family: 'Georgia', serif;
  line-height: 1.6;
}
</style>
```

### PremiumBblEditorOptionsAPI

The same editor component using Vue 2 Options API (for projects not using Composition API).

```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :placeholder="placeholder"
    :toolbar-config="toolbarConfig"
    @ready="handleReady"
  />
</template>

<script>
import { PremiumBblEditorOptionsAPI } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  
  data() {
    return {
      content: '<p>Options API Editor</p>',
      placeholder: 'Start writing with Options API...',
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true,
        link: true,
        image: true
      }
    }
  },
  
  methods: {
    handleReady(editor) {
      console.log('Options API Editor ready:', editor)
    }
  }
}
</script>
```

## Toolbar Components

### ToolbarMain

Complete toolbar with all formatting options.

```vue
<template>
  <div class="custom-editor">
    <ToolbarMain
      v-if="editor"
      :editor="editor"
      :config="toolbarConfig"
      :font-families="fontFamilies"
      :font-sizes="fontSizes"
      :line-heights="lineHeights"
      :allowed-headings="allowedHeadings"
      :source-code-mode="isSourceMode"
      @execute-command="executeCommand"
      @insert-link="openLinkModal"
      @insert-image="openImageModal"
      @insert-video="openVideoModal"
      @clear-formatting="clearFormatting"
      @toggle-source-code="toggleSourceCode"
    />
    
    <div class="editor-content">
      <editor-content :editor="editor" />
    </div>
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { ToolbarMain, useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent,
    ToolbarMain
  },
  
  setup() {
    const { editor, executeCommand } = useEditor({
      content: '<p>Custom toolbar implementation</p>'
    })

    return {
      editor,
      executeCommand
    }
  },
  
  data() {
    return {
      isSourceMode: false,
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true,
        textColor: true,
        highlight: true,
        fontFamily: true,
        fontSize: true,
        headings: true,
        lists: true,
        link: true,
        image: true,
        video: true,
        table: true
      },
      fontFamilies: ['Inter', 'Arial', 'Georgia'],
      fontSizes: ['14px', '16px', '18px', '20px'],
      lineHeights: ['1.2', '1.4', '1.6', '1.8'],
      allowedHeadings: [1, 2, 3, 4]
    }
  },
  
  methods: {
    openLinkModal() {
      console.log('Open link modal')
      // Your link modal logic
    },
    
    openImageModal() {
      console.log('Open image modal')
      // Your image modal logic
    },
    
    openVideoModal() {
      console.log('Open video modal')
      // Your video modal logic
    },
    
    clearFormatting() {
      this.executeCommand('unsetAllMarks')
      this.executeCommand('clearNodes')
    },
    
    toggleSourceCode() {
      this.isSourceMode = !this.isSourceMode
      // Toggle between visual and source code mode
    }
  }
}
</script>
```

### ToolbarGroup

Group related toolbar buttons together.

```vue
<template>
  <div class="custom-toolbar">
    <ToolbarGroup label="Text Formatting">
      <ToolbarButton
        :editor="editor"
        command="toggleBold"
        icon="B"
        tooltip="Bold"
        :is-active="editor && editor.isActive('bold')"
      />
      <ToolbarButton
        :editor="editor"
        command="toggleItalic"
        icon="I"
        tooltip="Italic"
        :is-active="editor && editor.isActive('italic')"
      />
      <ToolbarButton
        :editor="editor"
        command="toggleUnderline"
        icon="U"
        tooltip="Underline"
        :is-active="editor && editor.isActive('underline')"
      />
    </ToolbarGroup>
    
    <ToolbarGroup label="Structure">
      <ToolbarButton
        :editor="editor"
        command="toggleBulletList"
        icon="•"
        tooltip="Bullet List"
        :is-active="editor && editor.isActive('bulletList')"
      />
      <ToolbarButton
        :editor="editor"
        command="toggleOrderedList"
        icon="1."
        tooltip="Numbered List"
        :is-active="editor && editor.isActive('orderedList')"
      />
    </ToolbarGroup>
  </div>
</template>

<script>
import { ToolbarGroup, ToolbarButton } from 'vue2-premium-bbl-editor'

export default {
  components: {
    ToolbarGroup,
    ToolbarButton
  },
  
  props: {
    editor: {
      type: Object,
      required: true
    }
  }
}
</script>
```

### ToolbarButton

Individual toolbar button component.

```vue
<template>
  <div class="toolbar-buttons">
    <!-- Basic button -->
    <ToolbarButton
      :editor="editor"
      command="toggleBold"
      icon="B"
      tooltip="Bold (Ctrl+B)"
      :is-active="editor && editor.isActive('bold')"
      @click="handleBoldClick"
    />
    
    <!-- Button with custom icon -->
    <ToolbarButton
      :editor="editor"
      command="toggleItalic"
      tooltip="Italic (Ctrl+I)"
      :is-active="editor && editor.isActive('italic')"
    >
      <template #icon>
        <svg width="16" height="16" viewBox="0 0 24 24">
          <path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4h-8z"/>
        </svg>
      </template>
    </ToolbarButton>
    
    <!-- Dropdown button -->
    <ToolbarButton
      :editor="editor"
      :is-dropdown="true"
      tooltip="Heading"
      @click="toggleHeadingDropdown"
    >
      <template #icon>H</template>
      <template #dropdown v-if="showHeadingDropdown">
        <div class="heading-dropdown">
          <div @click="setHeading(1)">Heading 1</div>
          <div @click="setHeading(2)">Heading 2</div>
          <div @click="setHeading(3)">Heading 3</div>
          <div @click="setParagraph">Paragraph</div>
        </div>
      </template>
    </ToolbarButton>
  </div>
</template>

<script>
import { ToolbarButton } from 'vue2-premium-bbl-editor'

export default {
  components: {
    ToolbarButton
  },
  
  props: {
    editor: {
      type: Object,
      required: true
    }
  },
  
  data() {
    return {
      showHeadingDropdown: false
    }
  },
  
  methods: {
    handleBoldClick() {
      console.log('Bold button clicked')
      // Custom logic before/after bold toggle
    },
    
    toggleHeadingDropdown() {
      this.showHeadingDropdown = !this.showHeadingDropdown
    },
    
    setHeading(level) {
      this.editor.chain().focus().toggleHeading({ level }).run()
      this.showHeadingDropdown = false
    },
    
    setParagraph() {
      this.editor.chain().focus().setParagraph().run()
      this.showHeadingDropdown = false
    }
  }
}
</script>

<style scoped>
.toolbar-buttons {
  display: flex;
  gap: 4px;
  align-items: center;
}

.heading-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  background: white;
  border: 1px solid #e2e8f0;
  border-radius: 4px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  z-index: 10;
  min-width: 120px;
}

.heading-dropdown div {
  padding: 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid #f1f5f9;
}

.heading-dropdown div:hover {
  background: #f8fafc;
}

.heading-dropdown div:last-child {
  border-bottom: none;
}
</style>
```

## Menu Components

### EditorBubbleMenu

Text selection bubble menu that appears when text is selected.

```vue
<template>
  <div class="editor-with-bubble">
    <editor-content :editor="editor" />
    
    <EditorBubbleMenu
      v-if="editor"
      :editor="editor"
      :config="bubbleConfig"
      :show-link-options="true"
      :show-text-formatting="true"
      :show-text-styling="true"
      @execute-command="executeCommand"
      @open-link-modal="openLinkModal"
    />
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { EditorBubbleMenu, useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent,
    EditorBubbleMenu
  },
  
  setup() {
    const { editor, executeCommand } = useEditor({
      content: '<p>Select text to see the bubble menu</p>'
    })

    return {
      editor,
      executeCommand
    }
  },
  
  data() {
    return {
      bubbleConfig: {
        bold: true,
        italic: true,
        underline: true,
        strike: true,
        code: true,
        textColor: true,
        highlight: true,
        link: true
      }
    }
  },
  
  methods: {
    openLinkModal() {
      console.log('Open link modal from bubble menu')
      // Your link modal logic
    }
  }
}
</script>
```

### TableBubbleMenu

Table-specific bubble menu for table operations.

```vue
<template>
  <div class="editor-with-table-menu">
    <editor-content :editor="editor" />
    
    <TableBubbleMenu
      v-if="editor"
      :editor="editor"
      :show-row-controls="true"
      :show-column-controls="true"
      :show-cell-controls="true"
      :show-table-controls="true"
      @add-row-before="addRowBefore"
      @add-row-after="addRowAfter"
      @delete-row="deleteRow"
      @add-column-before="addColumnBefore"
      @add-column-after="addColumnAfter"
      @delete-column="deleteColumn"
      @merge-cells="mergeCells"
      @split-cell="splitCell"
      @delete-table="deleteTable"
    />
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { TableBubbleMenu, useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent,
    TableBubbleMenu
  },
  
  setup() {
    const { editor } = useEditor({
      content: `
        <table>
          <tr><th>Header 1</th><th>Header 2</th></tr>
          <tr><td>Cell 1</td><td>Cell 2</td></tr>
        </table>
      `
    })

    return { editor }
  },
  
  methods: {
    addRowBefore() {
      this.editor.chain().focus().addRowBefore().run()
    },
    
    addRowAfter() {
      this.editor.chain().focus().addRowAfter().run()
    },
    
    deleteRow() {
      this.editor.chain().focus().deleteRow().run()
    },
    
    addColumnBefore() {
      this.editor.chain().focus().addColumnBefore().run()
    },
    
    addColumnAfter() {
      this.editor.chain().focus().addColumnAfter().run()
    },
    
    deleteColumn() {
      this.editor.chain().focus().deleteColumn().run()
    },
    
    mergeCells() {
      this.editor.chain().focus().mergeCells().run()
    },
    
    splitCell() {
      this.editor.chain().focus().splitCell().run()
    },
    
    deleteTable() {
      this.editor.chain().focus().deleteTable().run()
    }
  }
}
</script>
```

### ImageBubbleMenu

Image-specific bubble menu for image operations.

```vue
<template>
  <div class="editor-with-image-menu">
    <editor-content :editor="editor" />
    
    <ImageBubbleMenu
      v-if="editor"
      :editor="editor"
      :show-alignment-controls="true"
      :show-resize-controls="true"
      :show-delete-control="true"
      :show-alt-text-control="true"
      @align-left="alignImageLeft"
      @align-center="alignImageCenter"
      @align-right="alignImageRight"
      @resize-image="resizeImage"
      @delete-image="deleteImage"
      @edit-alt-text="editAltText"
    />
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { ImageBubbleMenu, useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent,
    ImageBubbleMenu
  },
  
  setup() {
    const { editor } = useEditor({
      content: '<p>Click on an image to see the image menu</p>'
    })

    return { editor }
  },
  
  methods: {
    alignImageLeft() {
      // Custom image alignment logic
      console.log('Align image left')
    },
    
    alignImageCenter() {
      console.log('Align image center')
    },
    
    alignImageRight() {
      console.log('Align image right')
    },
    
    resizeImage(size) {
      console.log('Resize image to:', size)
    },
    
    deleteImage() {
      console.log('Delete image')
    },
    
    editAltText() {
      console.log('Edit alt text')
    }
  }
}
</script>
```

### VideoBubbleMenu

Video-specific bubble menu for video operations.

```vue
<template>
  <div class="editor-with-video-menu">
    <editor-content :editor="editor" />
    
    <VideoBubbleMenu
      v-if="editor"
      :editor="editor"
      :show-alignment-controls="true"
      :show-resize-controls="true"
      :show-playback-controls="true"
      :show-delete-control="true"
      @align-left="alignVideoLeft"
      @align-center="alignVideoCenter"
      @align-right="alignVideoRight"
      @resize-video="resizeVideo"
      @toggle-autoplay="toggleAutoplay"
      @toggle-controls="toggleControls"
      @delete-video="deleteVideo"
    />
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { VideoBubbleMenu, useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent,
    VideoBubbleMenu
  },
  
  setup() {
    const { editor } = useEditor({
      content: '<p>Add a video to see the video menu</p>'
    })

    return { editor }
  },
  
  methods: {
    alignVideoLeft() {
      console.log('Align video left')
    },
    
    alignVideoCenter() {
      console.log('Align video center')
    },
    
    alignVideoRight() {
      console.log('Align video right')
    },
    
    resizeVideo(size) {
      console.log('Resize video to:', size)
    },
    
    toggleAutoplay() {
      console.log('Toggle video autoplay')
    },
    
    toggleControls() {
      console.log('Toggle video controls')
    },
    
    deleteVideo() {
      console.log('Delete video')
    }
  }
}
</script>
```

## Modal Components

### ImageModal

Modal for uploading and configuring images.

```vue
<template>
  <div>
    <button @click="showImageModal = true">Insert Image</button>
    
    <ImageModal
      :visible="showImageModal"
      :upload-handler="uploadHandler"
      :max-file-size="maxFileSize"
      :allowed-types="allowedImageTypes"
      :show-url-input="true"
      :show-alt-text-input="true"
      :show-alignment-options="true"
      :show-size-options="true"
      @close="showImageModal = false"
      @insert="insertImage"
      @upload-progress="handleUploadProgress"
      @upload-error="handleUploadError"
    />
  </div>
</template>

<script>
import { ImageModal } from 'vue2-premium-bbl-editor'

export default {
  components: {
    ImageModal
  },
  
  data() {
    return {
      showImageModal: false,
      maxFileSize: 5 * 1024 * 1024, // 5MB
      allowedImageTypes: [
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/webp'
      ]
    }
  },
  
  methods: {
    async uploadHandler(file) {
      try {
        const formData = new FormData()
        formData.append('image', file)
        
        const response = await fetch('/api/upload/image', {
          method: 'POST',
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`Upload failed: ${response.statusText}`)
        }
        
        const data = await response.json()
        return {
          src: data.url,
          alt: file.name,
          width: data.width,
          height: data.height
        }
      } catch (error) {
        console.error('Image upload error:', error)
        throw error
      }
    },
    
    insertImage(imageData) {
      console.log('Insert image:', imageData)
      // Insert image into editor
      // this.editor.chain().focus().setImage(imageData).run()
    },
    
    handleUploadProgress(progress) {
      console.log('Upload progress:', progress)
    },
    
    handleUploadError(error) {
      console.error('Upload error:', error)
      alert(`Upload failed: ${error.message}`)
    }
  }
}
</script>
```

### VideoModal

Modal for uploading and configuring videos.

```vue
<template>
  <div>
    <button @click="showVideoModal = true">Insert Video</button>
    
    <VideoModal
      :visible="showVideoModal"
      :upload-handler="uploadHandler"
      :max-file-size="maxFileSize"
      :allowed-types="allowedVideoTypes"
      :show-url-input="true"
      :show-embed-input="true"
      :show-playback-options="true"
      :show-size-options="true"
      @close="showVideoModal = false"
      @insert="insertVideo"
      @upload-progress="handleUploadProgress"
      @upload-error="handleUploadError"
    />
  </div>
</template>

<script>
import { VideoModal } from 'vue2-premium-bbl-editor'

export default {
  components: {
    VideoModal
  },
  
  data() {
    return {
      showVideoModal: false,
      maxFileSize: 50 * 1024 * 1024, // 50MB
      allowedVideoTypes: [
        'video/mp4',
        'video/webm',
        'video/ogg'
      ]
    }
  },
  
  methods: {
    async uploadHandler(file) {
      try {
        const formData = new FormData()
        formData.append('video', file)
        
        const response = await fetch('/api/upload/video', {
          method: 'POST',
          body: formData
        })
        
        if (!response.ok) {
          throw new Error(`Upload failed: ${response.statusText}`)
        }
        
        const data = await response.json()
        return {
          src: data.url,
          poster: data.poster,
          width: data.width,
          height: data.height
        }
      } catch (error) {
        console.error('Video upload error:', error)
        throw error
      }
    },
    
    insertVideo(videoData) {
      console.log('Insert video:', videoData)
      // Insert video into editor
      // this.editor.chain().focus().setVideo(videoData).run()
    },
    
    handleUploadProgress(progress) {
      console.log('Upload progress:', progress)
    },
    
    handleUploadError(error) {
      console.error('Upload error:', error)
      alert(`Upload failed: ${error.message}`)
    }
  }
}
</script>
```

### LinkModal

Modal for creating and editing links.

```vue
<template>
  <div>
    <button @click="showLinkModal = true">Insert Link</button>
    
    <LinkModal
      :visible="showLinkModal"
      :initial-text="linkData.text"
      :initial-url="linkData.url"
      :initial-target="linkData.target"
      :show-text-input="true"
      :show-target-options="true"
      :show-title-input="true"
      :validate-url="true"
      @close="showLinkModal = false"
      @insert="insertLink"
      @update="updateLink"
      @remove="removeLink"
    />
  </div>
</template>

<script>
import { LinkModal } from 'vue2-premium-bbl-editor'

export default {
  components: {
    LinkModal
  },
  
  data() {
    return {
      showLinkModal: false,
      linkData: {
        text: '',
        url: '',
        target: '_blank'
      }
    }
  },
  
  methods: {
    insertLink(linkData) {
      console.log('Insert link:', linkData)
      // Insert link into editor
      // this.editor.chain().focus().setLink(linkData).run()
    },
    
    updateLink(linkData) {
      console.log('Update link:', linkData)
      // Update existing link
    },
    
    removeLink() {
      console.log('Remove link')
      // Remove link from editor
      // this.editor.chain().focus().unsetLink().run()
    }
  }
}
</script>
```

## Upload System Components

### UploadManager Integration

```vue
<template>
  <div class="upload-system-demo">
    <PremiumBblEditor
      v-model="content"
      @ready="onEditorReady"
    />
    
    <div class="upload-status" v-if="uploadStatus">
      <div class="progress-bar">
        <div 
          class="progress-fill" 
          :style="{ width: uploadProgress + '%' }"
        ></div>
      </div>
      <p>{{ uploadStatus }} - {{ uploadProgress }}%</p>
    </div>
  </div>
</template>

<script>
import { 
  PremiumBblEditor,
  UploadManager,
  LocalStorageAdapter,
  integrateTipTapUpload,
  createUploadConfig
} from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor
  },
  
  data() {
    return {
      content: '<p>Upload system integration example</p>',
      uploadManager: null,
      uploadStatus: null,
      uploadProgress: 0
    }
  },
  
  async created() {
    await this.initializeUploadSystem()
  },
  
  methods: {
    async initializeUploadSystem() {
      try {
        // Create upload configuration
        const config = createUploadConfig('localStorage', {
          validation: {
            maxSize: 10 * 1024 * 1024, // 10MB
            allowedTypes: [
              'image/jpeg', 'image/png', 'image/gif',
              'video/mp4', 'video/webm'
            ]
          },
          retry: {
            maxAttempts: 3,
            baseDelay: 1000
          }
        })
        
        // Initialize upload manager
        this.uploadManager = new UploadManager(config)
        
        // Register adapters
        const localAdapter = new LocalStorageAdapter({
          generateObjectUrl: true
        })
        this.uploadManager.registerAdapter(localAdapter)
        this.uploadManager.setDefaultAdapter('local-storage')
        
        // Set up event listeners
        this.setupUploadEvents()
        
      } catch (error) {
        console.error('Upload system initialization failed:', error)
      }
    },
    
    setupUploadEvents() {
      // Progress tracking
      this.uploadManager.on('progress', (progress) => {
        this.uploadProgress = Math.round(progress.percentage)
        this.uploadStatus = 'Uploading...'
      })
      
      // Upload completed
      this.uploadManager.on('uploadCompleted', (event) => {
        this.uploadStatus = 'Upload completed!'
        this.uploadProgress = 100
        
        setTimeout(() => {
          this.uploadStatus = null
          this.uploadProgress = 0
        }, 2000)
      })
      
      // Upload failed
      this.uploadManager.on('uploadFailed', (event) => {
        this.uploadStatus = `Upload failed: ${event.error.message}`
        this.uploadProgress = 0
        
        setTimeout(() => {
          this.uploadStatus = null
        }, 3000)
      })
    },
    
    onEditorReady(editor) {
      // Integrate upload system with editor
      integrateTipTapUpload(editor, this.uploadManager, {
        onStart: () => {
          this.uploadStatus = 'Starting upload...'
          this.uploadProgress = 0
        },
        onEnd: () => {
          // Upload process ended (success or failure)
        }
      })
    }
  },
  
  beforeDestroy() {
    if (this.uploadManager) {
      this.uploadManager.destroy()
    }
  }
}
</script>

<style scoped>
.upload-status {
  margin-top: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #e9ecef;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 10px;
}

.progress-fill {
  height: 100%;
  background: #007bff;
  transition: width 0.3s ease;
}
</style>
```

## Development Tools

### DiagnosticTool

Built-in diagnostic tool for troubleshooting.

```vue
<template>
  <div class="development-tools">
    <h3>Development Tools</h3>
    
    <!-- Main Editor -->
    <PremiumBblEditor
      v-model="content"
      @ready="handleReady"
      @error="handleError"
    />
    
    <!-- Diagnostic Tool -->
    <div class="diagnostic-section">
      <h4>Diagnostic Information</h4>
      <DiagnosticTool
        :show-dependency-check="true"
        :show-browser-info="true"
        :show-editor-state="true"
        :show-performance-metrics="true"
        :editor="editor"
        @diagnostic-complete="handleDiagnostic"
      />
    </div>
  </div>
</template>

<script>
import { PremiumBblEditor, DiagnosticTool } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor,
    DiagnosticTool
  },
  
  data() {
    return {
      content: '<p>Editor with diagnostic tools</p>',
      editor: null
    }
  },
  
  methods: {
    handleReady(editor) {
      this.editor = editor
      console.log('Editor ready for diagnostics')
    },
    
    handleError(error) {
      console.error('Editor error detected:', error)
    },
    
    handleDiagnostic(diagnosticData) {
      console.log('Diagnostic complete:', diagnosticData)
      
      // Check for issues
      if (diagnosticData.issues.length > 0) {
        console.warn('Issues found:', diagnosticData.issues)
      }
      
      // Performance metrics
      if (diagnosticData.performance) {
        console.log('Performance metrics:', diagnosticData.performance)
      }
    }
  }
}
</script>

<style scoped>
.development-tools {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

.diagnostic-section {
  margin-top: 30px;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}
</style>
```

### DebugHelper

Development debugging helper component.

```vue
<template>
  <div class="debug-environment" v-if="isDevelopment">
    <h3>Debug Environment</h3>
    
    <!-- Main Editor -->
    <PremiumBblEditor
      v-model="content"
      @ready="handleReady"
      @input="handleInput"
      @focus="handleFocus"
      @blur="handleBlur"
    />
    
    <!-- Debug Helper -->
    <div class="debug-section">
      <h4>Debug Information</h4>
      <DebugHelper
        :editor="editor"
        :show-editor-state="true"
        :show-content-analysis="true"
        :show-event-log="true"
        :show-performance-monitor="true"
        :auto-refresh="true"
        :refresh-interval="1000"
        @state-change="handleStateChange"
        @performance-update="handlePerformanceUpdate"
      />
    </div>
  </div>
</template>

<script>
import { PremiumBblEditor, DebugHelper } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor,
    DebugHelper
  },
  
  data() {
    return {
      content: '<p>Editor with debug helper</p>',
      editor: null
    }
  },
  
  computed: {
    isDevelopment() {
      return process.env.NODE_ENV === 'development'
    }
  },
  
  methods: {
    handleReady(editor) {
      this.editor = editor
      console.log('Editor ready for debugging')
    },
    
    handleInput(content) {
      console.log('Content changed:', content.length, 'characters')
    },
    
    handleFocus() {
      console.log('Editor focused')
    },
    
    handleBlur() {
      console.log('Editor blurred')
    },
    
    handleStateChange(state) {
      console.log('Editor state changed:', state)
    },
    
    handlePerformanceUpdate(metrics) {
      console.log('Performance metrics:', metrics)
      
      // Alert if performance is poor
      if (metrics.renderTime > 100) {
        console.warn('Slow render time detected:', metrics.renderTime, 'ms')
      }
    }
  }
}
</script>

<style scoped>
.debug-environment {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.debug-section {
  margin-top: 30px;
  padding: 20px;
  background: #1e1e1e;
  color: #d4d4d4;
  border-radius: 8px;
  font-family: 'Courier New', monospace;
}
</style>
```

## Composables

### useEditor

Core editor composable for custom implementations.

```vue
<template>
  <div class="custom-editor-implementation">
    <div class="editor-toolbar" v-if="editor">
      <button 
        @click="executeCommand('toggleBold')"
        :class="{ active: isActive('bold') }"
      >
        Bold
      </button>
      <button 
        @click="executeCommand('toggleItalic')"
        :class="{ active: isActive('italic') }"
      >
        Italic
      </button>
      <button @click="focus">Focus</button>
      <button @click="getContentExample">Get Content</button>
    </div>
    
    <div class="editor-content">
      <editor-content :editor="editor" />
    </div>
    
    <div class="editor-status">
      <p>Ready: {{ isEditorReady }}</p>
      <p>Content Length: {{ currentContent.length }}</p>
      <p v-if="editorError" class="error">Error: {{ editorError }}</p>
    </div>
  </div>
</template>

<script>
import { EditorContent } from '@tiptap/vue-2'
import { useEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    EditorContent
  },
  
  setup(props, { emit }) {
    // Use the editor composable
    const {
      editor,
      isEditorReady,
      currentContent,
      editorError,
      missingDependencies,
      executeCommand,
      isActive,
      getContent,
      setContent,
      focus,
      blur
    } = useEditor({
      value: '<p>Custom editor using useEditor composable</p>',
      placeholder: 'Start typing...',
      editable: true,
      autofocus: false,
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true
      },
      extensionConfig: {
        image: {
          allowResize: true
        }
      }
    }, emit)

    return {
      editor,
      isEditorReady,
      currentContent,
      editorError,
      missingDependencies,
      executeCommand,
      isActive,
      getContent,
      setContent,
      focus,
      blur
    }
  },
  
  methods: {
    getContentExample() {
      const htmlContent = this.getContent('html')
      const jsonContent = this.getContent('json')
      
      console.log('HTML Content:', htmlContent)
      console.log('JSON Content:', jsonContent)
    }
  }
}
</script>

<style scoped>
.custom-editor-implementation {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.editor-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 6px;
}

.editor-toolbar button {
  padding: 6px 12px;
  border: 1px solid #dee2e6;
  background: white;
  border-radius: 4px;
  cursor: pointer;
}

.editor-toolbar button:hover {
  background: #e9ecef;
}

.editor-toolbar button.active {
  background: #007bff;
  color: white;
  border-color: #007bff;
}

.editor-content {
  border: 1px solid #dee2e6;
  border-radius: 6px;
  min-height: 200px;
  padding: 16px;
}

.editor-status {
  margin-top: 16px;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 6px;
  font-size: 14px;
}

.error {
  color: #dc3545;
  font-weight: bold;
}
</style>
```

## Advanced Usage Patterns

### Multi-Editor Setup

```vue
<template>
  <div class="multi-editor-setup">
    <h2>Multi-Editor Setup</h2>
    
    <div class="editor-tabs">
      <button 
        v-for="(tab, index) in tabs" 
        :key="index"
        @click="activeTab = index"
        :class="{ active: activeTab === index }"
      >
        {{ tab.title }}
      </button>
    </div>
    
    <div class="editor-content">
      <PremiumBblEditor
        v-for="(tab, index) in tabs"
        :key="index"
        v-show="activeTab === index"
        v-model="tab.content"
        :placeholder="tab.placeholder"
        :toolbar-config="tab.toolbarConfig"
        @ready="handleEditorReady(index, $event)"
      />
    </div>
  </div>
</template>

<script>
import { PremiumBblEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor
  },
  
  data() {
    return {
      activeTab: 0,
      tabs: [
        {
          title: 'Article Content',
          content: '<h2>Article Title</h2><p>Article content...</p>',
          placeholder: 'Write your article...',
          toolbarConfig: {
            bold: true,
            italic: true,
            underline: true,
            headings: true,
            lists: true,
            link: true,
            image: true
          }
        },
        {
          title: 'Summary',
          content: '<p>Article summary...</p>',
          placeholder: 'Write a summary...',
          toolbarConfig: {
            bold: true,
            italic: true,
            lists: true
          }
        },
        {
          title: 'Notes',
          content: '<p>Internal notes...</p>',
          placeholder: 'Add notes...',
          toolbarConfig: {
            bold: true,
            italic: true,
            code: true,
            lists: true
          }
        }
      ],
      editors: []
    }
  },
  
  methods: {
    handleEditorReady(index, editor) {
      this.editors[index] = editor
      console.log(`Editor ${index} ready:`, editor)
    },
    
    getAllContent() {
      return this.tabs.map((tab, index) => ({
        title: tab.title,
        content: tab.content,
        editor: this.editors[index]
      }))
    },
    
    saveAllContent() {
      const allContent = this.getAllContent()
      console.log('Saving all content:', allContent)
      // Save to backend
    }
  }
}
</script>

<style scoped>
.multi-editor-setup {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

.editor-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  border-bottom: 1px solid #dee2e6;
}

.editor-tabs button {
  padding: 12px 20px;
  border: none;
  background: transparent;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  font-weight: 500;
}

.editor-tabs button:hover {
  background: #f8f9fa;
}

.editor-tabs button.active {
  border-bottom-color: #007bff;
  color: #007bff;
}

.editor-content {
  min-height: 400px;
}
</style>
```

### Form Integration

```vue
<template>
  <form @submit.prevent="submitForm" class="editor-form">
    <h2>Article Form with Editor</h2>
    
    <div class="bbl-form-group">
      <label for="title">Title:</label>
      <input 
        id="title"
        v-model="form.title" 
        type="text" 
        required 
        class="form-control"
      />
    </div>
    
    <div class="bbl-form-group">
      <label for="category">Category:</label>
      <select id="category" v-model="form.category" class="form-control">
        <option value="news">News</option>
        <option value="tutorial">Tutorial</option>
        <option value="review">Review</option>
      </select>
    </div>
    
    <div class="bbl-form-group">
      <label>Content:</label>
      <PremiumBblEditor
        v-model="form.content"
        placeholder="Write your article content..."
        :auto-save="true"
        :auto-save-interval="30000"
        :max-content-length="10000"
        @auto-save="handleAutoSave"
        @content-limit-exceeded="handleLimitExceeded"
        @ready="handleEditorReady"
      />
    </div>
    
    <div class="bbl-form-group">
      <label for="tags">Tags:</label>
      <input 
        id="tags"
        v-model="form.tags" 
        type="text" 
        placeholder="Comma-separated tags"
        class="form-control"
      />
    </div>
    
    <div class="form-actions">
      <button type="button" @click="saveDraft" class="btn btn-secondary">
        Save Draft
      </button>
      <button type="submit" class="btn btn-primary">
        Publish Article
      </button>
    </div>
    
    <div class="form-status" v-if="status">
      <p :class="statusClass">{{ status }}</p>
    </div>
  </form>
</template>

<script>
import { PremiumBblEditor } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor
  },
  
  data() {
    return {
      form: {
        title: '',
        category: 'news',
        content: '<p>Start writing your article...</p>',
        tags: ''
      },
      editor: null,
      status: '',
      statusClass: ''
    }
  },
  
  methods: {
    handleEditorReady(editor) {
      this.editor = editor
      console.log('Form editor ready')
    },
    
    handleAutoSave(content) {
      this.form.content = content
      this.saveDraft(true) // Auto-save as draft
    },
    
    handleLimitExceeded({ current, max }) {
      this.showStatus(`Content too long: ${current}/${max} characters`, 'error')
    },
    
    async saveDraft(isAutoSave = false) {
      try {
        const response = await fetch('/api/articles/draft', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            ...this.form,
            isDraft: true
          })
        })
        
        if (response.ok) {
          const message = isAutoSave ? 'Auto-saved' : 'Draft saved'
          this.showStatus(message, 'success')
        } else {
          throw new Error('Save failed')
        }
      } catch (error) {
        this.showStatus('Save failed', 'error')
      }
    },
    
    async submitForm() {
      try {
        // Validate form
        if (!this.form.title.trim()) {
          this.showStatus('Title is required', 'error')
          return
        }
        
        if (!this.form.content.trim() || this.form.content === '<p></p>') {
          this.showStatus('Content is required', 'error')
          return
        }
        
        // Submit form
        const response = await fetch('/api/articles', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            ...this.form,
            isDraft: false,
            publishedAt: new Date().toISOString()
          })
        })
        
        if (response.ok) {
          this.showStatus('Article published successfully!', 'success')
          // Reset form or redirect
        } else {
          throw new Error('Publish failed')
        }
      } catch (error) {
        this.showStatus('Publish failed', 'error')
      }
    },
    
    showStatus(message, type) {
      this.status = message
      this.statusClass = `status-${type}`
      
      setTimeout(() => {
        this.status = ''
        this.statusClass = ''
      }, 3000)
    }
  }
}
</script>

<style scoped>
.editor-form {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.bbl-form-group {
  margin-bottom: 20px;
}

.bbl-form-group label {
  display: block;
  margin-bottom: 8px;
  font-weight: 500;
  color: #374151;
}

.form-control {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 14px;
}

.form-control:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
}

.form-actions {
  display: flex;
  gap: 12px;
  margin-top: 30px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.2s;
}

.btn-primary {
  background: #3b82f6;
  color: white;
}

.btn-primary:hover {
  background: #2563eb;
}

.btn-secondary {
  background: #6b7280;
  color: white;
}

.btn-secondary:hover {
  background: #4b5563;
}

.form-status {
  margin-top: 20px;
  padding: 12px;
  border-radius: 6px;
}

.status-success {
  background: #d1fae5;
  color: #065f46;
  border: 1px solid #a7f3d0;
}

.status-error {
  background: #fee2e2;
  color: #991b1b;
  border: 1px solid #fca5a5;
}
</style>
```

This comprehensive guide covers all the components and usage patterns available in the Vue2 Premium BBL Editor package. Each example includes complete implementation details, event handling, and styling to help you integrate the components effectively in your projects.