# Vue 2 Premium BBL Editor

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.

## 🚀 Features

- ✅ **Vue 2.6 Compatible** - Full support for Vue 2.6+ applications
- ✅ **Production Ready** - Thoroughly tested and optimized for production use
- ✅ **Fully Configurable** - Extensive props for customizing every aspect
- ✅ **Rich Text Editing** - Complete formatting options (bold, italic, underline, etc.)
- ✅ **Advanced Media** - Resizable images and videos with upload support
- ✅ **Smart Tables** - Interactive tables with cell controls and resizing
- ✅ **Upload Management** - Comprehensive upload system with multiple adapters
- ✅ **Multiple Themes** - Default, minimal, and dark themes included
- ✅ **TypeScript Support** - Full TypeScript definitions included
- ✅ **Accessibility** - WCAG compliant with keyboard navigation
- ✅ **Auto-save** - Built-in auto-save functionality
- ✅ **Source Code View** - Toggle between visual and HTML source editing
- ✅ **External Integration** - Easy integration with existing projects

## 📦 Installation

```bash
npm install vue2-premium-bbl-editor
```

### PREVIEW

<img src="https://raw.githubusercontent.com/Mahadi74/vue2-premium-bbl-editor/refs/heads/main/public/preview.png?token=GHSAT0AAAAAAC2VZAZN5WMWV2SNVXGIKHW22LOIILA" width="100"/>

## 🎯 Quick Start

### Global Registration (Recommended)

```javascript
import Vue from 'vue'
import PremiumBblEditor from 'vue2-premium-bbl-editor'

// Register globally
Vue.use(PremiumBblEditor)

// Or register with options
Vue.use(PremiumBblEditor, {
  registerAllComponents: true // Registers all sub-components globally
})
```

### Component Registration

```javascript
// Composition API version (requires @vue/composition-api)
import { PremiumBblEditor } from 'vue2-premium-bbl-editor'

// Options API version (pure Vue 2)
import { PremiumBblEditorOptionsAPI } from 'vue2-premium-bbl-editor'

export default {
  components: {
    PremiumBblEditor,
    // or
    PremiumBblEditorOptionsAPI
  }
}
```

### Basic Usage

#### Composition API Version

```vue
<template>
  <div>
    <PremiumBblEditor
      v-model="content"
      placeholder="Start writing your content..."
      @input="handleInput"
      @ready="handleReady"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      content: '<p>Hello World!</p>'
    }
  },
  methods: {
    handleInput(content) {
      console.log('Content updated:', content)
    },
    handleReady(editor) {
      console.log('Editor is ready:', editor)
    }
  }
}
</script>
```

#### Options API Version

```vue
<template>
  <div>
    <PremiumBblEditorOptionsAPI
      v-model="content"
      placeholder="Start writing your content..."
      @input="handleInput"
      @ready="handleReady"
    />
  </div>
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>Hello World with Options API!</p>'
    }
  },
  methods: {
    handleInput(content) {
      console.log('Content updated:', content)
    },
    handleReady(editor) {
      console.log('Options API Editor is ready:', editor)
    }
  }
}
</script>
```

## 📋 Complete Component API

### Props

#### Content & Basic Configuration

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `value` | String | `''` | Editor content (v-model) |
| `placeholder` | String | `'Start writing...'` | Placeholder text when editor is empty |
| `editable` | Boolean | `true` | Whether editor content can be modified |
| `outputFormat` | String | `'html'` | Output format: 'html' or 'json' |
| `autofocus` | Boolean | `false` | Auto-focus editor on mount |
| `spellcheck` | Boolean | `true` | Enable browser spellcheck |

#### Layout & Appearance

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `maxHeight` | String/Number | `null` | Maximum editor height (px or CSS value) |
| `minHeight` | String/Number | `200` | Minimum editor height (px or CSS value) |
| `theme` | String | `'default'` | Theme: 'default', 'minimal', 'dark' |
| `editorClass` | String/Array/Object | `''` | Custom CSS classes for editor container |
| `toolbarClass` | String/Array/Object | `''` | Custom CSS classes for toolbar |
| `contentClass` | String/Array/Object | `''` | Custom CSS classes for content area |

#### UI Component Visibility

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `showToolbar` | Boolean | `true` | Show/hide main toolbar |
| `showBubbleMenu` | Boolean | `true` | Show/hide text selection bubble menu |
| `showTableBubbleMenu` | Boolean | `true` | Show/hide table-specific bubble menu |
| `showImageBubbleMenu` | Boolean | `true` | Show/hide image-specific bubble menu |
| `showVideoBubbleMenu` | Boolean | `true` | Show/hide video-specific bubble menu |

#### Toolbar Configuration

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `toolbarConfig` | Object | See below | Configure which toolbar buttons to show |

**Default Toolbar Configuration:**
```javascript
{
  // Text formatting
  bold: true,
  italic: true,
  underline: true,
  strike: true,
  code: true,
  
  // Text styling
  textColor: true,
  highlight: true,
  fontFamily: true,
  fontSize: true,
  
  // Alignment and spacing
  textAlign: true,
  lineHeight: true,
  
  // Structure
  headings: true,
  lists: true,
  blockquote: true,
  codeBlock: true,
  horizontalRule: true,
  
  // Media
  link: true,
  image: true,
  video: true,
  table: true,
  
  // Utilities
  clearFormatting: true,
  sourceCode: true,
  undo: true,
  redo: true
}
```

#### Extension Configuration

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `extensionConfig` | Object | See below | Configure extension behavior |

**Default Extension Configuration:**
```javascript
{
  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
  },
  textAlign: {
    types: ['heading', 'paragraph']
  }
}
```

#### Upload & Media Handling

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `uploadHandler` | Function | `null` | Custom upload handler function |
| `imageUploadUrl` | String | `null` | URL endpoint for image uploads |
| `videoUploadUrl` | String | `null` | URL endpoint for video uploads |
| `maxFileSize` | Number | `10485760` | Maximum file size in bytes (10MB) |
| `allowedImageTypes` | Array | `['image/jpeg', 'image/png', 'image/gif', 'image/webp']` | Allowed image MIME types |
| `allowedVideoTypes` | Array | `['video/mp4', 'video/webm', 'video/ogg']` | Allowed video MIME types |

#### Local File Base64 Management

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `useBase64Upload` | Boolean | `false` | Force base64 conversion even when upload URLs are provided |
| `base64Quality` | Number | `0.8` | Image compression quality (0.1 - 1.0) |
| `base64MaxWidth` | Number | `1920` | Maximum width for compressed images (px) |
| `base64MaxHeight` | Number | `1080` | Maximum height for compressed images (px) |
| `enableImageCompression` | Boolean | `true` | Enable automatic image compression |
| `preserveOriginalFileName` | Boolean | `true` | Preserve original file names in alt text |
| `base64Prefix` | String | `'data:'` | Custom prefix for base64 data URLs |

#### Content Restrictions

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `maxContentLength` | Number | `null` | Maximum content length in characters |
| `allowedHeadings` | Array | `[1, 2, 3, 4, 5, 6]` | Allowed heading levels |

#### Styling Options

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `fontFamilies` | Array | See below | Available font families |
| `fontSizes` | Array | See below | Available font sizes |
| `lineHeights` | Array | See below | Available line heights |

**Default Font Options:**
```javascript
// Font Families
['Inter', 'Arial', 'Helvetica', 'Times New Roman', 'Georgia', 'Courier New', 'Monaco', 'Menlo']

// Font Sizes
['12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px']

// Line Heights
['1', '1.2', '1.4', '1.6', '1.8', '2', '2.5', '3']
```

#### Auto-save Configuration

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `autoSave` | Boolean | `false` | Enable automatic content saving |
| `autoSaveInterval` | Number | `30000` | Auto-save interval in milliseconds |

### Events

| Event | Payload | Description |
|-------|---------|-------------|
| `input` | `content: string` | Emitted when content changes (v-model) |
| `update` | `content: string` | Emitted when content updates |
| `ready` | `editor: Editor` | Emitted when editor is ready for use |
| `created` | `editor: Editor` | Emitted when editor instance is created |
| `focus` | - | Emitted when editor gains focus |
| `blur` | - | Emitted when editor loses focus |
| `destroyed` | - | Emitted when editor is destroyed |
| `auto-save` | `content: string` | Emitted during auto-save |
| `content-limit-exceeded` | `{current: number, max: number}` | Emitted when content exceeds limit |
| `image-compressed` | `{originalSize: number, compressedSize: number, originalDimensions: object, compressedDimensions: object, compressionRatio: number}` | Emitted when image is compressed |
| `error` | `{type: string, message: string, ...}` | Emitted when errors occur |

### Methods

Access editor methods via template ref:

```vue
<template>
  <PremiumBblEditor
    ref="editor"
    v-model="content"
  />
</template>

<script>
export default {
  methods: {
    focusEditor() {
      this.$refs.editor.focus()
    },
    getContent() {
      return this.$refs.editor.getContent()
    },
    setContent(content) {
      this.$refs.editor.setContent(content)
    },
    executeCommand(command, options) {
      this.$refs.editor.executeCommand(command, options)
    }
  }
}
</script>
```

**Available Methods:**
- `focus()` - Focus the editor
- `blur()` - Blur the editor  
- `getContent(format?)` - Get editor content ('html' or 'json')
- `setContent(content, emitUpdate?)` - Set editor content
- `executeCommand(command, options?)` - Execute editor command

## 💡 Usage Examples

### 1. Basic Editor

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    placeholder="Start writing..."
    @input="handleInput"
    @ready="handleReady"
  />
</template>

<script>
export default {
  data() {
    return {
      content: '<p>Hello World!</p>'
    }
  },
  methods: {
    handleInput(content) {
      console.log('Content updated:', content)
    },
    handleReady(editor) {
      console.log('Editor is ready:', editor)
    }
  }
}
</script>
```

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    placeholder="Start writing..."
    @input="handleInput"
    @ready="handleReady"
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>Hello World with Options API!</p>'
    }
  },
  methods: {
    handleInput(content) {
      console.log('Content updated:', content)
    },
    handleReady(editor) {
      console.log('Options API Editor is ready:', editor)
    }
  }
}
</script>
```

### 2. Minimal Configuration

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    theme="minimal"
    :toolbar-config="{
      bold: true,
      italic: true,
      underline: true,
      link: true,
      lists: true,
      undo: true,
      redo: true
    }"
    placeholder="Minimal editor..."
  />
</template>
```

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    theme="minimal"
    :toolbar-config="minimalToolbarConfig"
    placeholder="Minimal editor with Options API..."
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>This is a minimal editor with limited features.</p>',
      minimalToolbarConfig: {
        bold: true,
        italic: true,
        underline: true,
        link: true,
        lists: true,
        undo: true,
        redo: true
      }
    }
  }
}
</script>
```

### 3. Advanced Configuration with Upload

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    :max-height="400"
    :auto-save="true"
    :auto-save-interval="15000"
    :upload-handler="customUploadHandler"
    :font-families="['Inter', 'Arial', 'Georgia']"
    :extension-config="{
      image: {
        allowResize: true,
        maxWidth: '800px'
      },
      table: {
        resizable: true,
        cellSelection: true
      }
    }"
    @auto-save="handleAutoSave"
    @ready="handleReady"
  />
</template>

<script>
export default {
  data() {
    return {
      content: '<h2>Advanced Editor</h2><p>With custom upload handling...</p>'
    }
  },
  methods: {
    async customUploadHandler(file) {
      const formData = new FormData()
      formData.append('file', file)
      
      const response = await fetch('/api/upload', {
        method: 'POST',
        body: formData
      })
      
      const data = await response.json()
      return { src: data.url, alt: file.name }
    },
    
    handleAutoSave(content) {
      // Save to your backend
      this.saveToServer(content)
    },
    
    handleReady(editor) {
      console.log('Editor ready with advanced features')
    }
  }
}
</script>
```

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :max-height="maxHeight"
    :auto-save="autoSave"
    :auto-save-interval="autoSaveInterval"
    :upload-handler="customUploadHandler"
    :font-families="fontFamilies"
    :extension-config="extensionConfig"
    @auto-save="handleAutoSave"
    @ready="handleReady"
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<h2>Advanced Options API Editor</h2><p>With comprehensive configuration...</p>',
      maxHeight: 400,
      autoSave: true,
      autoSaveInterval: 15000,
      fontFamilies: ['Inter', 'Arial', 'Georgia'],
      extensionConfig: {
        image: {
          allowResize: true,
          maxWidth: '800px',
          quality: 0.9
        },
        table: {
          resizable: true,
          cellSelection: true,
          allowRowControls: true
        },
        link: {
          autolink: true,
          linkOnPaste: true
        }
      }
    }
  },
  methods: {
    async customUploadHandler(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,
          width: data.width,
          height: data.height
        }
      } catch (error) {
        console.error('Upload error:', error)
        throw error
      }
    },
    
    handleAutoSave(content) {
      console.log('Auto-saving content...')
      this.saveToServer(content)
    },
    
    handleReady(editor) {
      console.log('Options API Editor ready with advanced features')
      // Store editor reference for later use
      this.editor = editor
    },
    
    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('Content saved successfully')
      } catch (error) {
        console.error('Save failed:', error)
      }
    },
    
    getAuthToken() {
      return localStorage.getItem('authToken') || ''
    }
  }
}
</script>
```

### 4. Read-only Display

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    :editable="false"
    :show-toolbar="false"
    :show-bubble-menu="false"
  />
</template>

<script>
export default {
  data() {
    return {
      content: `
        <h3>Read-only Content</h3>
        <p>This content is displayed in <strong>read-only mode</strong>.</p>
        <blockquote>
          <p>Perfect for displaying formatted content without editing capabilities.</p>
        </blockquote>
      `
    }
  }
}
</script>
```

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :editable="editable"
    :show-toolbar="showToolbar"
    :show-bubble-menu="showBubbleMenu"
    :show-table-bubble-menu="showTableBubbleMenu"
    :show-image-bubble-menu="showImageBubbleMenu"
    :show-video-bubble-menu="showVideoBubbleMenu"
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: `
        <h3>Read-only Content (Options API)</h3>
        <p>This content is displayed in <strong>read-only mode</strong> using Options API.</p>
        <blockquote>
          <p>Perfect for displaying formatted content without editing capabilities.</p>
        </blockquote>
        <ul>
          <li>No toolbar visible</li>
          <li>No bubble menus</li>
          <li>Content cannot be modified</li>
        </ul>
      `,
      editable: false,
      showToolbar: false,
      showBubbleMenu: false,
      showTableBubbleMenu: false,
      showImageBubbleMenu: false,
      showVideoBubbleMenu: false
    }
  }
}
</script>
```

### 5. Custom Styling & Dark Theme

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    theme="dark"
    editor-class="custom-editor"
    toolbar-class="custom-toolbar"
    content-class="custom-content"
    placeholder="Dark themed editor..."
  />
</template>

<style>
.custom-editor {
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.custom-toolbar {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

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

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :theme="theme"
    :editor-class="editorClass"
    :toolbar-class="toolbarClass"
    :content-class="contentClass"
    :placeholder="placeholder"
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>This Options API editor uses custom styling and dark theme.</p>',
      theme: 'dark',
      placeholder: 'Dark themed Options API editor...',
      editorClass: 'custom-editor-options',
      toolbarClass: 'custom-toolbar-options',
      contentClass: 'custom-content-options'
    }
  }
}
</script>

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

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

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

### 6. Local Base64 File Management

#### Composition API Version
```vue
<template>
  <PremiumBblEditor
    v-model="content"
    :use-base64-upload="true"
    :enable-image-compression="true"
    :base64-quality="0.8"
    :base64-max-width="1920"
    :base64-max-height="1080"
    :preserve-original-file-name="true"
    placeholder="Upload images for local base64 conversion..."
    @image-compressed="handleImageCompressed"
    @ready="handleReady"
  />
</template>

<script>
export default {
  data() {
    return {
      content: '<p>Upload images to see base64 conversion with compression!</p>'
    }
  },
  methods: {
    handleImageCompressed(compressionData) {
      console.log('Image compressed:', {
        originalSize: compressionData.originalSize,
        compressedSize: compressionData.compressedSize,
        compressionRatio: compressionData.compressionRatio,
        savings: Math.round(((compressionData.originalSize - compressionData.compressedSize) / compressionData.originalSize) * 100) + '%'
      })
    },
    
    handleReady(editor) {
      console.log('Editor ready with base64 management')
    }
  }
}
</script>
```

#### Options API Version
```vue
<template>
  <PremiumBblEditorOptionsAPI
    v-model="content"
    :use-base64-upload="useBase64"
    :enable-image-compression="enableCompression"
    :base64-quality="quality"
    :base64-max-width="maxWidth"
    :base64-max-height="maxHeight"
    :preserve-original-file-name="preserveNames"
    placeholder="Options API with base64 management..."
    @image-compressed="onImageCompressed"
    @ready="onEditorReady"
  />
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>Options API editor with base64 file management!</p>',
      useBase64: true,
      enableCompression: true,
      quality: 0.8,
      maxWidth: 1920,
      maxHeight: 1080,
      preserveNames: true
    }
  },
  methods: {
    onImageCompressed(data) {
      console.log('Options API - Image compressed:', data)
      
      // Show compression statistics
      this.showCompressionStats(data)
    },
    
    onEditorReady(editor) {
      console.log('Options API Editor ready with base64 management')
      this.editorInstance = editor
    },
    
    showCompressionStats(data) {
      const savings = Math.round(((data.originalSize - data.compressedSize) / data.originalSize) * 100)
      alert(`Image compressed successfully!\nOriginal: ${this.formatFileSize(data.originalSize)}\nCompressed: ${this.formatFileSize(data.compressedSize)}\nSavings: ${savings}%`)
    },
    
    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]
    }
  }
}
</script>
```

### 7. Event Handling & Method Access

#### Composition API Version
```vue
<template>
  <div>
    <PremiumBblEditor
      ref="editor"
      v-model="content"
      @input="handleInput"
      @focus="handleFocus"
      @blur="handleBlur"
      @ready="handleReady"
      @auto-save="handleAutoSave"
      @content-limit-exceeded="handleLimitExceeded"
    />
    
    <div class="editor-controls">
      <button @click="focusEditor">Focus Editor</button>
      <button @click="getEditorContent">Get Content</button>
      <button @click="setEditorContent">Set Content</button>
      <button @click="executeCustomCommand">Bold Text</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      content: '<p>Editor with comprehensive event handling...</p>'
    }
  },
  methods: {
    handleInput(content) {
      console.log('Content changed:', content.length, 'characters')
    },
    
    handleFocus() {
      console.log('Editor focused')
    },
    
    handleBlur() {
      console.log('Editor blurred')
    },
    
    handleReady(editor) {
      console.log('Editor ready:', editor)
    },
    
    handleAutoSave(content) {
      console.log('Auto-saving content...')
      // Save to backend
    },
    
    handleLimitExceeded({ current, max }) {
      alert(`Content limit exceeded: ${current}/${max} characters`)
    },
    
    // Method examples
    focusEditor() {
      this.$refs.editor.focus()
    },
    
    getEditorContent() {
      const content = this.$refs.editor.getContent()
      console.log('Current content:', content)
    },
    
    setEditorContent() {
      this.$refs.editor.setContent('<p>New content set programmatically!</p>')
    },
    
    executeCustomCommand() {
      this.$refs.editor.executeCommand('toggleBold')
    }
  }
}
</script>
```

#### Options API Version
```vue
<template>
  <div>
    <PremiumBblEditorOptionsAPI
      ref="editorOptionsAPI"
      v-model="content"
      :max-content-length="maxContentLength"
      :auto-save="autoSave"
      :auto-save-interval="autoSaveInterval"
      @input="handleInput"
      @focus="handleFocus"
      @blur="handleBlur"
      @ready="handleReady"
      @auto-save="handleAutoSave"
      @content-limit-exceeded="handleLimitExceeded"
      @error="handleError"
    />
    
    <div class="editor-controls">
      <button @click="focusEditor">Focus Editor</button>
      <button @click="blurEditor">Blur Editor</button>
      <button @click="getEditorContent">Get Content</button>
      <button @click="setEditorContent">Set Content</button>
      <button @click="executeCustomCommand">Toggle Bold</button>
      <button @click="checkActiveState">Check Bold State</button>
      <button @click="clearContent">Clear Content</button>
    </div>
    
    <div class="editor-status" v-if="editorStatus">
      <h4>Editor Status</h4>
      <p>Content Length: {{ contentLength }}</p>
      <p>Is Bold Active: {{ isBoldActive }}</p>
      <p>Last Action: {{ lastAction }}</p>
    </div>
  </div>
</template>

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

export default {
  components: {
    PremiumBblEditorOptionsAPI
  },
  data() {
    return {
      content: '<p>Options API Editor with comprehensive event handling and method access...</p>',
      maxContentLength: 5000,
      autoSave: true,
      autoSaveInterval: 20000,
      editorInstance: null,
      editorStatus: true,
      contentLength: 0,
      isBoldActive: false,
      lastAction: 'None'
    }
  },
  methods: {
    handleInput(content) {
      this.contentLength = content.length
      this.lastAction = 'Content changed'
      console.log('Options API - Content changed:', content.length, 'characters')
    },
    
    handleFocus() {
      this.lastAction = 'Editor focused'
      console.log('Options API - Editor focused')
    },
    
    handleBlur() {
      this.lastAction = 'Editor blurred'
      console.log('Options API - Editor blurred')
    },
    
    handleReady(editor) {
      this.editorInstance = editor
      this.lastAction = 'Editor ready'
      console.log('Options API - Editor ready:', editor)
    },
    
    handleAutoSave(content) {
      this.lastAction = 'Auto-saved'
      console.log('Options API - Auto-saving content...')
      this.saveToServer(content)
    },
    
    handleLimitExceeded({ current, max }) {
      this.lastAction = `Content limit exceeded: ${current}/${max}`
      alert(`Content limit exceeded: ${current}/${max} characters`)
    },
    
    handleError(error) {
      this.lastAction = `Error: ${error.type}`
      console.error('Options API - Editor error:', error)
    },
    
    // Method examples using the Options API component
    focusEditor() {
      this.$refs.editorOptionsAPI.focus()
      this.lastAction = 'Focus method called'
    },
    
    blurEditor() {
      this.$refs.editorOptionsAPI.blur()
      this.lastAction = 'Blur method called'
    },
    
    getEditorContent() {
      const htmlContent = this.$refs.editorOptionsAPI.getContent('html')
      const jsonContent = this.$refs.editorOptionsAPI.getContent('json')
      
      console.log('HTML Content:', htmlContent)
      console.log('JSON Content:', jsonContent)
      this.lastAction = 'Get content method called'
    },
    
    setEditorContent() {
      const newContent = `
        <h3>New Content Set Programmatically</h3>
        <p>This content was set using the <strong>setContent</strong> method in Options API.</p>
        <ul>
          <li>Method called at: ${new Date().toLocaleTimeString()}</li>
          <li>Using Options API component</li>
        </ul>
      `
      this.$refs.editorOptionsAPI.setContent(newContent)
      this.lastAction = 'Set content method called'
    },
    
    executeCustomCommand() {
      this.$refs.editorOptionsAPI.executeCommand('toggleBold')
      this.checkActiveState()
      this.lastAction = 'Toggle bold command executed'
    },
    
    checkActiveState() {
      this.isBoldActive = this.$refs.editorOptionsAPI.isActive('bold')
      this.lastAction = 'Checked bold active state'
    },
    
    clearContent() {
      this.$refs.editorOptionsAPI.setContent('<p></p>')
      this.lastAction = 'Content cleared'
    },
    
    async saveToServer(content) {
      try {
        // Simulate API call
        await new Promise(resolve => setTimeout(resolve, 1000))
        console.log('Options API - Content saved to server')
      } catch (error) {
        console.error('Options API - Save failed:', error)
      }
    }
  }
}
</script>

<style scoped>
.editor-controls {
  margin: 20px 0;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.editor-controls button {
  padding: 8px 16px;
  background: #3b82f6;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

.editor-controls button:hover {
  background: #2563eb;
}

.editor-status {
  margin-top: 20px;
  padding: 15px;
  background: #f8f9fa;
  border: 1px solid #dee2e6;
  border-radius: 6px;
}

.editor-status h4 {
  margin-top: 0;
  color: #495057;
}

.editor-status p {
  margin: 5px 0;
  font-size: 14px;
  color: #6c757d;
}
</style>
```

## 🔌 Upload System Integration

The editor includes a comprehensive upload management system for handling file uploads with multiple adapters.

### Basic Upload Setup

```vue
<template>
  <PremiumBblEditor
    v-model="content"
    @ready="onEditorReady"
  />
</template>

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

export default {
  data() {
    return {
      content: '<p>Try uploading images...</p>',
      uploadManager: null
    }
  },
  
  async created() {
    // Create upload configuration
    const config = createUploadConfig('localStorage', {
      validation: {
        maxSize: 5 * 1024 * 1024, // 5MB
        allowedTypes: ['image/jpeg', 'image/png', 'image/gif']
      }
    })
    
    // Initialize upload manager
    this.uploadManager = new UploadManager(config)
    
    // Register local storage adapter
    const adapter = new LocalStorageAdapter()
    this.uploadManager.registerAdapter(adapter)
    this.uploadManager.setDefaultAdapter('local-storage')
  },
  
  methods: {
    onEditorReady(editor) {
      // Integrate upload system with editor
      integrateTipTapUpload(editor, this.uploadManager, {
        onStart: () => console.log('Upload started'),
        onEnd: () => console.log('Upload finished')
      })
    }
  }
}
</script>
```

### Custom Upload Adapter

```javascript
// Create custom adapter for your API
class CustomApiAdapter {
  constructor(options) {
    this.name = 'custom-api'
    this.apiUrl = options.apiUrl
    this.headers = options.headers || {}
  }

  async upload(file, options) {
    const formData = new FormData()
    formData.append('file', file)

    const response = await fetch(this.apiUrl, {
      method: 'POST',
      headers: this.headers,
      body: formData
    })

    if (!response.ok) {
      throw new Error(`Upload failed: ${response.statusText}`)
    }

    const result = await response.json()
    return {
      url: result.url,
      size: file.size,
      metadata: {
        fileName: file.name,
        fileType: file.type
      }
    }
  }
}

// Register and use
const adapter = new CustomApiAdapter({
  apiUrl: '/api/upload',
  headers: { 'Authorization': 'Bearer your-token' }
})
uploadManager.registerAdapter(adapter)
uploadManager.setDefaultAdapter('custom-api')
```

### Upload Event Handling

```javascript
// Listen to upload events
uploadManager.on('progress', (progress) => {
  console.log(`Upload progress: ${progress.percentage}%`)
})

uploadManager.on('uploadCompleted', (event) => {
  console.log('Upload completed:', event.result.url)
})

uploadManager.on('uploadFailed', (event) => {
  console.error('Upload failed:', event.error.message)
})
```

## 🧩 Individual Component Usage

Import and use individual components for custom implementations:

```javascript
import {
  PremiumBblEditor,
  PremiumBblEditorOptionsAPI,
  ToolbarMain,
  ToolbarGroup,
  ToolbarButton,
  EditorBubbleMenu,
  TableBubbleMenu,
  ImageBubbleMenu,
  VideoBubbleMenu,
  ImageModal,
  VideoModal,
  LinkModal,
  DiagnosticTool,
  DebugHelper,
  useEditor
} from 'vue2-premium-bbl-editor'
```

### Available Components

#### Main Components
- `PremiumBblEditor` - Main editor component (Composition API)
- `PremiumBblEditorOptionsAPI` - Main editor component (Options API)
- `DiagnosticTool` - Built-in diagnostic and troubleshooting tool
- `DebugHelper` - Development debugging helper

#### Toolbar Components
- `ToolbarMain` - Complete toolbar component
- `ToolbarGroup` - Toolbar button group container
- `ToolbarButton` - Individual toolbar button

#### Menu Components
- `EditorBubbleMenu` - Text selection bubble menu
- `TableBubbleMenu` - Table-specific bubble menu
- `ImageBubbleMenu` - Image-specific bubble menu
- `VideoBubbleMenu` - Video-specific bubble menu

#### Modal Components
- `ImageModal` - Image upload and configuration modal
- `VideoModal` - Video upload and configuration modal
- `LinkModal` - Link creation and editing modal

#### Composables
- `useEditor` - Core editor composable for custom implementations

### Custom Implementation Example

```vue
<template>
  <div class="custom-editor">
    <ToolbarMain
      v-if="editor"
      :editor="editor"
      :config="toolbarConfig"
      @execute-command="executeCommand"
    />
    
    <div class="editor-content">
      <editor-content :editor="editor" />
    </div>
    
    <EditorBubbleMenu
      v-if="editor"
      :editor="editor"
      :config="toolbarConfig"
    />
  </div>
</template>

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

export default {
  components: {
    EditorContent,
    ToolbarMain,
    EditorBubbleMenu
  },
  
  setup() {
    const { editor, executeCommand } = useEditor({
      content: '<p>Custom editor implementation</p>',
      extensions: [
        // Your custom extensions
      ]
    })

    return {
      editor,
      executeCommand,
      toolbarConfig: {
        bold: true,
        italic: true,
        underline: true
      }
    }
  }
}
</script>
```

## 🔌 Extensions & Customization

The package includes custom extensions that enhance the editing experience:

### Available Extensions
- `ResizableImage` - Enhanced image handling with resize controls
- `ResizableVideo` - Video embedding with resize functionality  
- `CustomTableCell` - Enhanced table cell with controls
- `CustomTableHeader` - Enhanced table header with controls

### Using Extensions Directly

```javascript
import { ResizableImage, ResizableVideo } from 'vue2-premium-bbl-editor'
import { Editor } from '@tiptap/vue-2'

const editor = new Editor({
  extensions: [
    ResizableImage.configure({
      allowResize: true,
      allowAlignment: true,
      maxWidth: '800px'
    }),
    ResizableVideo.configure({
      allowResize: true,
      autoplay: false
    })
  ]
})
```

## 🌐 External Project Integration

For detailed integration instructions for external projects, see our [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md).

### Quick Integration

```bash
# Install in your existing project
npm install vue2-premium-bbl-editor

# Install required dependencies
npm install @vue/composition-api @tiptap/core @tiptap/vue-2 @tiptap/starter-kit
```

```vue
<template>
  <PremiumBblEditor
    v-model="content"
    @ready="onEditorReady"
  />
</template>

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

export default {
  components: { PremiumBblEditor },
  data() {
    return {
      content: '<p>Start editing...</p>'
    }
  },
  methods: {
    onEditorReady(editor) {
      console.log('Editor ready in external project!')
    }
  }
}
</script>
```

## 🧪 Development & Testing

```bash
# Install dependencies
npm install

# Run development server
npm run serve

# Build library
npm run build:lib

# Run tests
npm test

# Lint code
npm run lint
```

### Development Tools

The package includes built-in development and diagnostic tools:

```vue
<template>
  <div>
    <!-- Your editor -->
    <PremiumBblEditor v-model="content" />
    
    <!-- Development tools -->
    <DiagnosticTool v-if="isDevelopment" />
    <DebugHelper v-if="isDevelopment" />
  </div>
</template>

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

export default {
  components: {
    PremiumBblEditor,
    DiagnosticTool,
    DebugHelper
  },
  computed: {
    isDevelopment() {
      return process.env.NODE_ENV === 'development'
    }
  }
}
</script>
```

## 🔧 Troubleshooting

### Common Issues

1. **Editor not loading**: Check if all required dependencies are installed
2. **Upload not working**: Verify upload handler configuration
3. **Styling issues**: Ensure CSS is properly imported
4. **TypeScript errors**: Check type definitions import

### Diagnostic Tools

Use the built-in diagnostic tool to identify issues:

```vue
<template>
  <div>
    <PremiumBblEditor v-model="content" />
    <DiagnosticTool />
  </div>
</template>
```

### Debug Mode

Enable debug mode for detailed logging:

```vue
<template>
  <PremiumBblEditor
    v-model="content"
    :debug="true"
  />
</template>
```

For more troubleshooting help, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).

## 📚 Documentation

- [Installation Guide](INSTALLATION.md)
- [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md)
- [Upload System Documentation](src/upload/README.md)
- [Troubleshooting Guide](TROUBLESHOOTING.md)
- [API Reference](types/index.d.ts)
- [Examples](examples/)

## 📄 License

MIT License - see [LICENSE](LICENSE) file for details.

## 🤝 Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## 📞 Support

- 📧 Email: support@example.com
- 🐛 Issues: [GitHub Issues](https://github.com/Mahadi74/vue2-premium-bbl-editor/issues)
- 📖 Documentation: [Full Documentation](https://github.com/Mahadi74/vue2-premium-bbl-editor/wiki)

## 🙏 Acknowledgments

- [Tiptap](https://tiptap.dev/) - The headless editor framework
- [ProseMirror](https://prosemirror.net/) - The foundation
- [Vue.js](https://vuejs.org/) - The progressive framework