{"_id":"@beefree.io/vue-email-builder","_rev":"3-d884273bf3fe8a2b5bed4be8df359904","name":"@beefree.io/vue-email-builder","dist-tags":{"latest":"1.1.1"},"versions":{"1.1.0":{"name":"@beefree.io/vue-email-builder","version":"1.1.0","keywords":["vue","vue3","vue-component","beefree","beefree-sdk","drag-and-drop","drag-and-drop-editor","collaborative-editing","email-builder","email-designer","email-editor","page-builder","page-designer","page-editor","popup-builder","popup-designer","popup-editor","file-manager","landing-pages","newsletters","responsive-emails","composable","editor","low-code","no-code","real-time-collaboration","visual-editor","wysiwyg"],"author":{"url":"https://www.beefree.io","name":"Beefree","email":"dev@beefree.io"},"license":"Apache-2.0","_id":"@beefree.io/vue-email-builder@1.1.0","maintainers":[{"name":"gaggero","email":"davide.gaggero@beefree.io"},{"name":"robmar","email":"rmarchet@gmail.com"},{"name":"pinkynrg","email":"biggyapple@gmail.com"},{"name":"davide.ponti","email":"davide.ponti@beefree.io"},{"name":"clarissabarbieri","email":"clarissa.barbieri@growens.io"},{"name":"mailupinc.2012","email":"dev@beefree.io"},{"name":"sferrario","email":"simone.ferrario@beefree.io"}],"homepage":"https://github.com/BeefreeSDK/vue-email-builder#readme","bugs":{"url":"https://github.com/BeefreeSDK/vue-email-builder/issues"},"dist":{"shasum":"e1d39ea43c4ff04dbe333ea3366900cfd88b59e1","tarball":"https://registry.npmjs.org/@beefree.io/vue-email-builder/-/vue-email-builder-1.1.0.tgz","fileCount":19,"integrity":"sha512-Kr3IoXpfkrroYwG9AoQY4wsuHmrse5dOPYBGHHFhvYrOYy3J60OgqXD83yzF1SmoavEQfirvwTTZTxr1dqMMxw==","signatures":[{"sig":"MEUCIBNHiG8w9luYuq3VLm0xqYu1CaREE+ArLTDIlyAUQv8+AiEAxVfZ1a7XrvOg17+BHBsQVyymslZVu7XVWmyxH0iYhfE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":198212},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.es.js","engines":{"npm":">=9.0.0","node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.js"}},"gitHead":"120287b70a16253671286e2261fecb212f3d43d4","scripts":{"lint":"eslint ./src --ext ts,vue","test":"vitest","build":"vite build --config vite.lib.config.ts","clean":"rimraf dist","start":"vite --config vite.config.ts","format":"prettier . --write","prepare":"husky","release":"yarn guard:main-branch && yarn prerelease && standard-version && git push --follow-tags --no-verify","test:ci":"vitest run","coverage":"vitest run --coverage","prebuild":"yarn clean","prestart":"yarn clean","prerelease":"git pull && yarn prebuild && yarn test:ci && yarn build","publish:npm":"yarn guard:main-branch && yarn build && npm publish --access public","format:check":"prettier . --check","release:beta":"yarn prerelease && standard-version --prerelease beta && git push --follow-tags --no-verify","test:example":"vitest run --config vitest.example.config.ts","release:alpha":"yarn prerelease && standard-version --prerelease alpha && git push --follow-tags --no-verify","coverage:example":"vitest run --coverage --config vitest.example.config.ts","release:unstable":"yarn prerelease && standard-version --prerelease $(git branch --show-current | sed 's/\\//-/g') && git push --follow-tags --no-verify","guard:main-branch":"test \"$(git rev-parse --abbrev-ref HEAD)\" = \"main\" || (echo 'Error: releases must be published from the main branch.' && exit 1)"},"_npmUser":{"name":"mailupinc.2012","email":"dev@beefree.io"},"repository":{"url":"git+https://github.com/BeefreeSDK/vue-email-builder.git","type":"git"},"_npmVersion":"10.9.4","description":"Vue.js wrapper for the Beefree SDK – A framework-specific package that provides the Builder component and composables to integrate the Beefree SDK (Email Builder, Page Builder, File Manager, Popup Builder) into Vue.js applications","directories":{},"lint-staged":{"*.{ts,vue}":"eslint"},"sideEffects":false,"_nodeVersion":"22.22.0","dependencies":{"@beefree.io/sdk":"^11.2.1"},"_hasShrinkwrap":false,"packageManager":"yarn@4.12.0","devDependencies":{"vue":"^3.5.17","vite":"^6.3.5","husky":"^9.1.7","jsdom":"^26.1.0","tslib":"^2.8.1","eslint":"^10.0.3","rimraf":"^6.0.1","vitest":"^3.0.0","globals":"^16.3.0","vue-tsc":"^2.2.12","prettier":"3.8.1","typescript":"^5.9.2","lint-staged":"^16.1.5","@commitlint/cli":"^20.5.0","@vue/test-utils":"^2.4.6","vite-plugin-dts":"^4.5.4","standard-version":"^9.5.0","@vue/compiler-sfc":"^3.5.17","eslint-plugin-vue":"^10.8.0","vue-eslint-parser":"^10.4.0","@vitejs/plugin-vue":"^5.2.4","@testing-library/dom":"^10.4.1","eslint-config-prettier":"^10.1.8","@vitest/coverage-istanbul":"^3.2.4","@vue/eslint-config-typescript":"^14.5.1","@commitlint/config-conventional":"^20.0.0"},"peerDependencies":{"vue":">=3.3"},"_npmOperationalInternal":{"tmp":"tmp/vue-email-builder_1.1.0_1773662630140_0.46030234735075326","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@beefree.io/vue-email-builder","version":"1.1.1","keywords":["vue","vue3","vue-component","beefree","beefree-sdk","drag-and-drop","drag-and-drop-editor","collaborative-editing","email-builder","email-designer","email-editor","page-builder","page-designer","page-editor","popup-builder","popup-designer","popup-editor","file-manager","landing-pages","newsletters","responsive-emails","composable","editor","low-code","no-code","real-time-collaboration","visual-editor","wysiwyg"],"author":{"url":"https://www.beefree.io","name":"Beefree","email":"dev@beefree.io"},"license":"Apache-2.0","_id":"@beefree.io/vue-email-builder@1.1.1","maintainers":[{"name":"gaggero","email":"davide.gaggero@beefree.io"},{"name":"robmar","email":"rmarchet@gmail.com"},{"name":"pinkynrg","email":"biggyapple@gmail.com"},{"name":"davide.ponti","email":"davide.ponti@beefree.io"},{"name":"clarissabarbieri","email":"clarissa.barbieri@growens.io"},{"name":"mailupinc.2012","email":"dev@beefree.io"},{"name":"sferrario","email":"simone.ferrario@beefree.io"}],"homepage":"https://github.com/BeefreeSDK/vue-email-builder#readme","bugs":{"url":"https://github.com/BeefreeSDK/vue-email-builder/issues"},"dist":{"shasum":"3feffbcdce5bd82cd139fefd006cb2e613c4aa33","tarball":"https://registry.npmjs.org/@beefree.io/vue-email-builder/-/vue-email-builder-1.1.1.tgz","fileCount":19,"integrity":"sha512-PMNkKSZn6ANPhsZuj1bCD/Dvai6sPQv8Nfxc6af+sIsOq4juElQZFjfTbHOngSwJrPKcxpL2pK2nVDGOA/B9FQ==","signatures":[{"sig":"MEYCIQD2MVch1g8sOE8qNDJf1MrHP/rqbX42TbUCniHJCamxSgIhAIYMJ+yhg871Dg8lyL7yfPExNRWRQuTHzvi16kaLJpEB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":198280},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.es.js","engines":{"npm":">=9.0.0","node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.js"}},"gitHead":"3632d90096c3b5accea821b263bc2ec5adf44c17","scripts":{"lint":"eslint ./src --ext ts,vue","test":"vitest","build":"vite build --config vite.lib.config.ts","clean":"rimraf dist","start":"vite --config vite.config.ts","format":"prettier . --write","prepare":"husky","release":"yarn guard:main-branch && yarn prerelease && standard-version && git push --follow-tags --no-verify","test:ci":"vitest run","coverage":"vitest run --coverage","prebuild":"yarn clean","prestart":"yarn clean","prerelease":"git pull && yarn prebuild && yarn test:ci && yarn build","publish:npm":"yarn guard:main-branch && yarn build && npm publish --access public","format:check":"prettier . --check","release:beta":"yarn prerelease && standard-version --prerelease beta && git push --follow-tags --no-verify","test:example":"vitest run --config vitest.example.config.ts","release:alpha":"yarn prerelease && standard-version --prerelease alpha && git push --follow-tags --no-verify","coverage:example":"vitest run --coverage --config vitest.example.config.ts","release:unstable":"yarn prerelease && standard-version --prerelease $(git branch --show-current | sed 's/\\//-/g') && git push --follow-tags --no-verify","guard:main-branch":"test \"$(git rev-parse --abbrev-ref HEAD)\" = \"main\" || (echo 'Error: releases must be published from the main branch.' && exit 1)"},"_npmUser":{"name":"mailupinc.2012","email":"dev@beefree.io"},"repository":{"url":"git+https://github.com/BeefreeSDK/vue-email-builder.git","type":"git"},"_npmVersion":"10.9.4","description":"Vue.js wrapper for the Beefree SDK – A framework-specific package that provides the Builder component and composables to integrate the Beefree SDK (Email Builder, Page Builder, File Manager, Popup Builder) into Vue.js applications","directories":{},"lint-staged":{"*.{ts,vue}":"eslint"},"sideEffects":false,"_nodeVersion":"22.22.1","dependencies":{"@beefree.io/sdk":"^11.2.1"},"_hasShrinkwrap":false,"packageManager":"yarn@4.12.0","devDependencies":{"vue":"^3.5.17","vite":"^6.3.5","husky":"^9.1.7","jsdom":"^26.1.0","tslib":"^2.8.1","eslint":"^10.0.3","rimraf":"^6.0.1","vitest":"^3.0.0","globals":"^16.3.0","vue-tsc":"^2.2.12","prettier":"3.8.1","typescript":"^5.9.2","lint-staged":"^16.1.5","@commitlint/cli":"^20.5.0","@vue/test-utils":"^2.4.6","vite-plugin-dts":"^4.5.4","standard-version":"^9.5.0","@vue/compiler-sfc":"^3.5.17","eslint-plugin-vue":"^10.8.0","vue-eslint-parser":"^10.4.0","@vitejs/plugin-vue":"^5.2.4","@testing-library/dom":"^10.4.1","eslint-config-prettier":"^10.1.8","@vitest/coverage-istanbul":"^3.2.4","@vue/eslint-config-typescript":"^14.5.1","@commitlint/config-conventional":"^20.0.0"},"peerDependencies":{"vue":">=3.3"},"_npmOperationalInternal":{"tmp":"tmp/vue-email-builder_1.1.1_1773663340159_0.19948504937819367","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-03-16T12:03:50.081Z","modified":"2026-03-16T13:48:04.273Z","1.1.0":"2026-03-16T12:03:50.311Z","1.1.1":"2026-03-16T12:15:40.320Z"},"bugs":{"url":"https://github.com/BeefreeSDK/vue-email-builder/issues"},"author":{"url":"https://www.beefree.io","name":"Beefree","email":"dev@beefree.io"},"license":"Apache-2.0","homepage":"https://github.com/BeefreeSDK/vue-email-builder#readme","keywords":["vue","vue3","vue-component","beefree","beefree-sdk","drag-and-drop","drag-and-drop-editor","collaborative-editing","email-builder","email-designer","email-editor","page-builder","page-designer","page-editor","popup-builder","popup-designer","popup-editor","file-manager","landing-pages","newsletters","responsive-emails","composable","editor","low-code","no-code","real-time-collaboration","visual-editor","wysiwyg"],"repository":{"url":"git+https://github.com/BeefreeSDK/vue-email-builder.git","type":"git"},"description":"Vue.js wrapper for the Beefree SDK – A framework-specific package that provides the Builder component and composables to integrate the Beefree SDK (Email Builder, Page Builder, File Manager, Popup Builder) into Vue.js applications","maintainers":[{"email":"davide.gaggero@beefree.io","name":"gaggero"},{"email":"rmarchet@gmail.com","name":"robmar"},{"email":"biggyapple@gmail.com","name":"pinkynrg"},{"email":"davide.ponti@beefree.io","name":"davide.ponti"},{"email":"clarissa.barbieri@growens.io","name":"clarissabarbieri"},{"email":"dev@beefree.io","name":"mailupinc.2012"},{"email":"marco.bianchi@beefree.io","name":"marco.bianchi"},{"email":"simone.ferrario@beefree.io","name":"sferrario"}],"readme":"# Beefree SDK Vue.js Components\n\n[![npm version](https://badge.fury.io/js/%40beefree.io%2Fvue-email-builder.svg)](https://www.npmjs.com/package/@beefree.io/vue-email-builder)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue)](https://www.typescriptlang.org/)\n[![Vue](https://img.shields.io/badge/Vue-3.5-42d392)](https://vuejs.org/)\n\nA Vue 3 wrapper for the [Beefree SDK](https://www.beefree.io/), providing the Builder component and composables to integrate the Beefree email, page, and popup builder into Vue.js applications.\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/BeefreeSDK/vue-email-builder/main/docs/vue-email-builder.png\" alt=\"Beefree SDK Vue.js Email Builder with co-editing\" width=\"800\" />\n</p>\n\n## Table of Contents\n\n- [What is Beefree SDK?](#what-is-beefree-sdk)\n- [Overview](#overview)\n- [Compatibility](#compatibility)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [API Reference](#api-reference)\n- [Composable: useBuilder](#composable-usebuilder)\n- [Best Practices](#best-practices)\n- [Advanced Usage](#advanced-usage)\n- [Examples](#examples)\n- [FAQ](#faq)\n- [Development](#development)\n- [Other Frameworks](#other-frameworks)\n- [License](#license)\n\n## What is Beefree SDK?\n\n[Beefree SDK](https://www.beefree.io/) is a drag-and-drop visual content builder that lets your users design professional emails, landing pages, and popups — without writing code. It powers thousands of SaaS applications worldwide, offering a white-label, embeddable editing experience with real-time collaborative editing, responsive design output, and extensive customization options.\n\nThis Vue package provides a `Builder` component and a `useBuilder` composable that handle SDK initialization, lifecycle management, and configuration updates — giving you a Vue-friendly API to integrate the full Beefree editing experience into your application.\n\n## Overview\n\n### Features\n\n- **Simple Vue Integration** - Drop-in component with minimal setup\n- **Composition API** - `useBuilder` composable for programmatic control\n- **Dynamic Configuration** - Update builder configuration reactively\n- **Collaborative Editing** - Support for shared/collaborative sessions\n- **TypeScript Support** - Full TypeScript definitions included\n- **Customizable** - Full access to Beefree SDK configuration options\n\n## Compatibility\n\n| Requirement | Version                                           |\n| ----------- | ------------------------------------------------- |\n| Vue         | >= 3.3                                            |\n| Node.js     | >= 18.0.0                                         |\n| TypeScript  | >= 4.7 (optional, but recommended)                |\n| Browsers    | Chrome, Firefox, Safari, Edge (latest 2 versions) |\n\n## Installation\n\n```bash\nnpm install @beefree.io/vue-email-builder\n# or\nyarn add @beefree.io/vue-email-builder\n```\n\n### Peer Dependencies\n\nThis package requires **Vue 3.3+** as a peer dependency:\n\n```bash\nnpm install vue\n```\n\n## Quick Start\n\n### 1. Get your credentials\n\nSign up at [developers.beefree.io](https://developers.beefree.io) to get your `client_id` and `client_secret`.\n\n### 2. Set up token generation on your backend\n\nYour backend server should exchange credentials for a short-lived token (see [Security: Server-Side Token Generation](#-security-server-side-token-generation) below for details):\n\n```javascript\n// Example: Node.js/Express backend endpoint\napp.post('/api/beefree/token', async (req, res) => {\n  const response = await fetch('https://auth.getbee.io/apiauth', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      client_id: process.env.BEEFREE_CLIENT_ID,\n      client_secret: process.env.BEEFREE_CLIENT_SECRET,\n      grant_type: 'password',\n    }),\n  })\n  res.json(await response.json())\n})\n```\n\n### 3. Integrate the builder in your Vue app\n\n```vue\n<template>\n  <div>\n    <div>\n      <button @click=\"preview()\">Preview</button>\n      <button @click=\"save()\">Save</button>\n    </div>\n    <Builder v-if=\"token\" :token=\"token\" :config=\"config\" @bb-save=\"onSave\" @bb-error=\"onError\" />\n    <div v-else>Loading builder...</div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue'\nimport { Builder, useBuilder } from '@beefree.io/vue-email-builder'\nimport type { IToken } from '@beefree.io/vue-email-builder'\n\nconst token = ref<IToken | null>(null)\n\nconst config = {\n  uid: 'user-123',\n  container: 'bee-container',\n  language: 'en-US',\n}\n\nconst { save, preview } = useBuilder(config)\n\nonMounted(async () => {\n  const res = await fetch('/api/beefree/token', { method: 'POST' })\n  token.value = await res.json()\n})\n\nfunction onSave(args: [string, string, string | null, number, string | null]) {\n  const [pageJson, pageHtml] = args\n  console.log('Saved:', { pageJson, pageHtml })\n}\n\nfunction onError(error: unknown) {\n  console.error('Builder error:', error)\n}\n</script>\n```\n\n## API Reference\n\n### `Builder` Component\n\nThe component that wraps the Beefree SDK. Use it for email, page, popup, or file-manager flows by passing the appropriate token and config.\n\n#### Props\n\n| Prop        | Type                 | Default                                  | Description                                    |\n| ----------- | -------------------- | ---------------------------------------- | ---------------------------------------------- |\n| `token`     | `IToken`             | **required**                             | Authentication token from Beefree API          |\n| `template`  | `IEntityContentJson` | `null`                                   | Template JSON to load                          |\n| `config`    | `IBeeConfig`         | `{ container: 'beefree-sdk-container' }` | SDK configuration                              |\n| `width`     | `string`             | `'100%'`                                 | Container width                                |\n| `height`    | `string`             | `'100%'`                                 | Container height                               |\n| `shared`    | `boolean`            | `false`                                  | Enable collaborative editing session           |\n| `sessionId` | `string`             | `null`                                   | Session ID to join (for collaborative editing) |\n| `loaderUrl` | `string`             | `null`                                   | Custom SDK loader URL                          |\n| `bucketDir` | `string`             | `undefined`                              | Custom bucket directory                        |\n\n#### Events\n\nAll events are prefixed with `bb-` (Beefree Builder) to avoid collisions with native DOM events:\n\n| Event                         | SDK Callback               | Payload                                                    |\n| ----------------------------- | -------------------------- | ---------------------------------------------------------- |\n| `bb-save`                     | `onSave`                   | `[pageJson, pageHtml, ampHtml, templateVersion, language]` |\n| `bb-save-as-template`         | `onSaveAsTemplate`         | `[pageJson, templateVersion]`                              |\n| `bb-send`                     | `onSend`                   | `htmlFile`                                                 |\n| `bb-error`                    | `onError`                  | `error`                                                    |\n| `bb-warning`                  | `onWarning`                | `warning`                                                  |\n| `bb-load`                     | `onLoad`                   | `value`                                                    |\n| `bb-change`                   | `onChange`                 | `[json, detail, version]`                                  |\n| `bb-auto-save`                | `onAutoSave`               | `json`                                                     |\n| `bb-start`                    | `onStart`                  | —                                                          |\n| `bb-comment`                  | `onComment`                | `[comment, action]`                                        |\n| `bb-info`                     | `onInfo`                   | `info`                                                     |\n| `bb-preview`                  | `onPreview`                | `isOpen`                                                   |\n| `bb-toggle-preview`           | `onTogglePreview`          | `isOpen`                                                   |\n| `bb-preview-change`           | `onPreviewChange`          | `value`                                                    |\n| `bb-save-row`                 | `onSaveRow`                | `[rowJson, rowHtml, rowMeta]`                              |\n| `bb-remote-change`            | `onRemoteChange`           | `[json, detail, version]`                                  |\n| `bb-session-change`           | `onSessionChange`          | `value`                                                    |\n| `bb-session-started`          | `onSessionStarted`         | `value`                                                    |\n| `bb-template-language-change` | `onTemplateLanguageChange` | `{ label, value, isMain }`                                 |\n| `bb-view-change`              | `onViewChange`             | `value`                                                    |\n| `bb-load-workspace`           | `onLoadWorkspace`          | `value`                                                    |\n\n### Handling Builder Events\n\nUse Vue's native event system to react to builder events. All events use the `bb-` prefix:\n\n```vue\n<template>\n  <Builder\n    :token=\"token\"\n    :config=\"config\"\n    @bb-save=\"onSave\"\n    @bb-error=\"onError\"\n    @bb-session-started=\"onSessionStarted\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nfunction onSave(args: [string, string, string | null, number, string | null]) {\n  const [pageJson, pageHtml] = args\n  console.log('Saved:', { pageJson, pageHtml })\n}\n\nfunction onError(error: unknown) {\n  console.error('Builder error:', error)\n}\n</script>\n```\n\n> **Note for developers coming from React:** The `Builder` component also supports defining callbacks directly in the config object (e.g., `onSave`, `onError`). If both are provided, the config callback fires first, then the Vue event is emitted. While this works, the events-based approach shown above is the idiomatic Vue pattern and is recommended for new projects.\n\n## Composable: `useBuilder`\n\nThe `useBuilder` composable provides programmatic control over a builder instance. It must be called at the top level of `<script setup>` (as with all Vue composables).\n\n```vue\n<script setup lang=\"ts\">\nimport { useBuilder } from '@beefree.io/vue-email-builder'\n\nconst config = {\n  container: 'bee-editor',\n  uid: 'user-123',\n  language: 'en-US',\n}\n\nconst {\n  save,\n  load,\n  preview,\n  togglePreview,\n  updateConfig,\n  getTemplateJson,\n  switchTemplateLanguage,\n} = useBuilder(config)\n\nasync function changeLanguage(lang: string) {\n  await updateConfig({ language: lang })\n}\n</script>\n```\n\n### How It Works\n\nThe composable connects to the builder instance through the `container` ID:\n\n1. You call `useBuilder(config)` with a config that includes a `container` ID.\n2. When a `Builder` component with a matching container mounts, the composable automatically binds to its SDK instance.\n3. Methods like `save()` and `preview()` delegate to the live SDK instance via closures — reactivity is maintained without `computed` wrappers.\n4. When the component unmounts, the composable cleans up its config registry entry.\n\n### Available Methods\n\n| Method                           | Description                               |\n| -------------------------------- | ----------------------------------------- |\n| `updateConfig(partial)`          | Updates builder configuration dynamically |\n| `save(options?)`                 | Triggers save action                      |\n| `saveAsTemplate()`               | Saves as template                         |\n| `send(args?)`                    | Sends the email                           |\n| `load(template)`                 | Loads a template JSON                     |\n| `reload(template, options?)`     | Reloads without loading dialog            |\n| `preview()`                      | Opens preview                             |\n| `togglePreview()`                | Toggles preview                           |\n| `switchPreview(args?)`           | Switches preview language                 |\n| `toggleComments()`               | Toggles comments panel                    |\n| `toggleStructure()`              | Toggles structure outlines                |\n| `toggleMergeTagsPreview()`       | Toggles merge tag preview                 |\n| `switchTemplateLanguage(args)`   | Switches content language                 |\n| `getTemplateJson()`              | Returns template JSON                     |\n| `getConfig()`                    | Returns current config                    |\n| `loadConfig(args, options?)`     | Loads new config                          |\n| `loadStageMode(args)`            | Loads stage mode                          |\n| `loadWorkspace(type)`            | Loads workspace                           |\n| `loadRows()`                     | Loads rows                                |\n| `showComment(comment)`           | Shows a comment                           |\n| `updateToken(token)`             | Updates auth token                        |\n| `execCommand(command, options?)` | Executes editor command                   |\n| `startFileManager(config, ...)`  | Starts file manager                       |\n| `join(config, sessionId, ...)`   | Joins shared session                      |\n| `start(config, template, ...)`   | Starts builder                            |\n\n## Best Practices\n\n### 🔒 Security: Server-Side Token Generation\n\n**⚠️ CRITICAL:** Never expose your Beefree API credentials in frontend code!\n\n**❌ Bad (Insecure):**\n\n```typescript\n// DON'T DO THIS!\nconst token = await fetch('https://auth.getbee.io/loginV2', {\n  method: 'POST',\n  body: JSON.stringify({\n    client_id: 'your-client-id', // ❌ Exposed!\n    client_secret: 'your-secret', // ❌ Exposed!\n  }),\n})\n```\n\n**✅ Good (Secure):**\n\n1. **Backend API endpoint** (Node.js/Express example):\n\n```javascript\n// backend/routes/auth.js\napp.post('/api/beefree/token', async (req, res) => {\n  const response = await fetch('https://auth.getbee.io/apiauth', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      client_id: process.env.BEEFREE_CLIENT_ID,\n      client_secret: process.env.BEEFREE_CLIENT_SECRET,\n      uid: req.user.id,\n    }),\n  })\n\n  const token = await response.json()\n  res.json(token)\n})\n```\n\n2. **Frontend:**\n\n```vue\n<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue'\nimport type { IToken } from '@beefree.io/vue-email-builder'\n\nconst token = ref<IToken | null>(null)\n\nonMounted(async () => {\n  const response = await fetch('/api/beefree/token', {\n    method: 'POST',\n    credentials: 'include',\n  })\n  token.value = await response.json()\n})\n</script>\n```\n\n### 🎯 Unique Container IDs\n\nWhen using multiple builders on the same page, ensure unique `container` IDs:\n\n```vue\n<script setup lang=\"ts\">\nconst builder1 = useBuilder({ container: 'builder-1', uid: 'user-1' })\nconst builder2 = useBuilder({ container: 'builder-2', uid: 'user-2' })\n</script>\n```\n\n### 📝 Reactive Configuration\n\nUse `reactive()` for configs that need runtime updates (e.g., language switching). The `Builder` component deep-watches its config prop and syncs callbacks automatically:\n\n```vue\n<script setup lang=\"ts\">\nimport { reactive } from 'vue'\n\nconst config = reactive({\n  uid: 'user-123',\n  container: 'bee-editor',\n  language: 'en-US',\n  onSave: (json: string, html: string) => {\n    console.log('Saved:', { json, html })\n  },\n})\n\nfunction changeLanguage(lang: string) {\n  config.language = lang\n}\n</script>\n```\n\n### 🔄 Collaborative Editing\n\nFor collaborative sessions, share the `sessionId` between users:\n\n```vue\n<template>\n  <!-- Host creates the session -->\n  <Builder\n    :token=\"token\"\n    :config=\"hostConfig\"\n    :shared=\"true\"\n    @bb-session-started=\"onSessionStarted\"\n  />\n\n  <!-- Guest joins with sessionId -->\n  <Builder\n    v-if=\"sessionId && guestToken\"\n    :token=\"guestToken\"\n    :config=\"guestConfig\"\n    :shared=\"true\"\n    :session-id=\"sessionId\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst sessionId = ref<string | null>(null)\n\nfunction onSessionStarted(event: { sessionId?: string }) {\n  if (event?.sessionId) {\n    sessionId.value = event.sessionId\n  }\n}\n</script>\n```\n\n## Advanced Usage\n\n### Custom Content Dialogs\n\n```typescript\nconst config = {\n  contentDialog: {\n    saveRow: {\n      label: 'Save to Library',\n      handler: async (resolve) => {\n        const rowName = await showCustomDialog()\n        resolve({ name: rowName })\n      },\n    },\n    addOn: {\n      handler: async (resolve) => {\n        const content = await fetchCustomContent()\n        resolve(content)\n      },\n    },\n  },\n}\n```\n\n### External Content Sources\n\n```typescript\nconst config = {\n  rowsConfiguration: {\n    externalContentURLs: [\n      {\n        name: 'My Saved Rows',\n        handle: 'saved-rows',\n        isLocal: true,\n      },\n    ],\n  },\n  hooks: {\n    getRows: {\n      handler: async (resolve, reject, args) => {\n        if (args.handle === 'saved-rows') {\n          const rows = await fetchSavedRows()\n          resolve(rows)\n        } else {\n          reject('Handle not found')\n        }\n      },\n    },\n  },\n}\n```\n\n### Mentions/Merge Tags\n\n```typescript\nconst config = {\n  hooks: {\n    getMentions: {\n      handler: async (resolve) => {\n        const mentions = [\n          { username: 'FirstName', value: '{{firstName}}', uid: 'fn' },\n          { username: 'LastName', value: '{{lastName}}', uid: 'ln' },\n        ]\n        resolve(mentions)\n      },\n    },\n  },\n}\n```\n\n## Examples\n\nThe [`/example`](example/) directory contains a fully working application that demonstrates:\n\n- Token authentication flow\n- Collaborative editing with template preservation\n- Save/preview actions and downloads from builder callbacks (`Save` -> `.html`, `Save as Template` -> `.json`)\n- Multi-language UI switching (header + example control labels outside the builder)\n- Sample/blank template toggle with local blank template fallback\n- Different builder modes (email, page, popup, file manager) via config\n- Per-instance control bars in co-editing mode\n- Keyboard-accessible split divider with ARIA attributes\n- Reusable toast notification system\n\n**Quick start:**\n\n```bash\ncd example\ncp .env.sample .env   # Fill in your Beefree credentials\ncd ..\nyarn install\nyarn start            # Opens at http://localhost:5173\n```\n\n## FAQ\n\n### How do I authenticate with the Beefree SDK?\n\nAuthentication requires a `client_id` and `client_secret`, which you get by signing up at [developers.beefree.io](https://developers.beefree.io). These credentials should **never** be exposed in frontend code. Instead, create a backend endpoint that exchanges them for a short-lived token and pass that token to the `Builder` component. See [Security: Server-Side Token Generation](#-security-server-side-token-generation) for a complete example.\n\n### Can I use this with Nuxt, Vite, or other Vue frameworks?\n\nYes. This package works with any Vue 3-based framework. For **Nuxt 3**, wrap the builder in a `<ClientOnly>` component since the SDK requires the DOM. For **Vite**, it works out of the box. For **Quasar** or other Vue 3 frameworks, use them as you would any Vue component.\n\n### Does it support collaborative editing?\n\nYes. Set `:shared=\"true\"` on the `Builder` component to create a collaborative session. The `bb-session-started` event provides a `sessionId` that other users can use to join the same session. See [Collaborative Editing](#-collaborative-editing) for a full example.\n\n### What email clients are supported?\n\nThe Beefree SDK generates responsive HTML that is compatible with all major email clients, including Gmail, Outlook (desktop and web), Apple Mail, Yahoo Mail, and mobile email apps. The output follows email HTML best practices with inline CSS and table-based layouts for maximum compatibility.\n\n### Can I customize the builder UI?\n\nYes. The Beefree SDK supports extensive UI customization including custom content dialogs, external content sources, merge tags, special links, and more. See [Advanced Usage](#advanced-usage) and the [Beefree SDK Documentation](https://docs.beefree.io/) for the full range of customization options.\n\n### How do I load an existing template?\n\nPass your template JSON to the `:template` prop of the `Builder` component. You can also use the `load` method from the `useBuilder` composable to programmatically load a template at any time after initialization.\n\n### Can I use the Options API instead of `<script setup>`?\n\nThe `useBuilder` composable must be called within a Vue setup context (either `<script setup>` or inside the `setup()` function). The Builder component works with both the Options API and the Composition API.\n\n## Development\n\n### Prerequisites\n\n- Node.js >= 18 (see `.nvmrc`)\n- Yarn 4\n\n### Setup\n\n```bash\n# Install dependencies\nyarn install\n\n# Start the example dev server\nyarn start\n\n# Run tests\nyarn test\n\n# Run tests once (CI)\nyarn test:ci\n\n# Lint\nyarn lint\n\n# Build library\nyarn build\n```\n\n### Building\n\n```bash\nyarn build\n```\n\nThe library build uses **Vite library mode** (`vite.lib.config.ts`) and generates ESM, CJS, and DTS outputs.\n\nOutputs:\n\n- `dist/index.js` - CommonJS bundle\n- `dist/index.es.js` - ES module bundle\n- `dist/index.d.ts` - TypeScript definitions\n\n### Project Structure\n\n```\nsrc/                      # Library source\n  components/             # Vue component (Builder)\n  composables/            # Vue composables (useBuilder, useRegistry)\n  types.ts                # TypeScript types\n  constants.ts            # Constants\n  index.ts                # Public API exports\n  __tests__/              # Test files\n\nexample/                  # Example application (Vite dev server)\n  App.vue                 # Root component with toast system\n  BeefreeExample.vue      # Demo component with co-editing\n  beefree-token.ts        # Token service (demo only)\n  environment.ts          # Environment config\n  i18n/                   # Localization files (22 languages)\n```\n\n### Environment Variables\n\nCopy `example/.env.sample` to `example/.env` and fill in your Beefree SDK credentials:\n\n```\nVITE_EMAIL_BUILDER_CLIENT_ID=your-client-id\nVITE_EMAIL_BUILDER_CLIENT_SECRET=your-client-secret\nVITE_EMAIL_BUILDER_USER_ID=your-user-id\n\nVITE_PAGE_BUILDER_CLIENT_ID=your-client-id\nVITE_PAGE_BUILDER_CLIENT_SECRET=your-client-secret\nVITE_PAGE_BUILDER_USER_ID=your-user-id\n\nVITE_POPUP_BUILDER_CLIENT_ID=your-client-id\nVITE_POPUP_BUILDER_CLIENT_SECRET=your-client-secret\nVITE_POPUP_BUILDER_USER_ID=your-user-id\n\nVITE_FILE_MANAGER_CLIENT_ID=your-client-id\nVITE_FILE_MANAGER_CLIENT_SECRET=your-client-secret\nVITE_FILE_MANAGER_USER_ID=your-user-id\n\n# Optional: override sample template URLs used by the example UI\nVITE_EMAIL_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee\nVITE_PAGE_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee-page\nVITE_POPUP_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee-popup\n```\n\n## Troubleshooting\n\n### Builder not loading\n\n1. Verify token is valid and not expired\n2. Check the browser console for errors\n3. Ensure `container` ID is unique on the page\n4. Confirm `uid` is set in the config\n\n### Builder not responding to `useBuilder` methods\n\nThe `container` ID in your `useBuilder` config must match the `container` in the `Builder` component's config. The composable binds to the SDK instance by container ID.\n\n## Other Frameworks\n\nBeefree SDK wrappers are available for the following frameworks:\n\n| Framework | Package                             | Repository                                                                              |\n| --------- | ----------------------------------- | --------------------------------------------------------------------------------------- |\n| React     | `@beefree.io/react-email-builder`   | [BeefreeSDK/react-email-builder](https://github.com/BeefreeSDK/react-email-builder)     |\n| Angular   | `@beefree.io/angular-email-builder` | [BeefreeSDK/angular-email-builder](https://github.com/BeefreeSDK/angular-email-builder) |\n\n## License\n\n[Apache License 2.0](LICENSE)\n\n## Support\n\nFor issues related to:\n\n- **This Vue wrapper**: Open an issue on [this repository](https://github.com/BeefreeSDK/vue-email-builder/issues)\n- **Beefree SDK**: Visit [Beefree Developer Documentation](https://docs.beefree.io/)\n- **Account/billing**: Contact [Beefree Support](https://www.beefree.io/support/)\n\n## Resources\n\n- [Beefree SDK Documentation](https://docs.beefree.io/)\n- [Beefree API Reference](https://docs.beefree.io/beefree-sdk/apis)\n- [Examples and Guides](https://github.com/BeefreeSDK/beefree-sdk-examples)\n","readmeFilename":"README.md"}