{"_id":"@amusendame/beakblock-vue","_rev":"3-5c5bd7a4e6945b8f89c7c7da5dcb12cf","name":"@amusendame/beakblock-vue","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@amusendame/beakblock-vue","version":"0.1.0","keywords":["editor","rich-text","prosemirror","block-editor","wysiwyg","notion-like","vue","vue3","typescript","text-editor"],"license":"Apache-2.0","_id":"@amusendame/beakblock-vue@0.1.0","maintainers":[{"name":"amusendame","email":"aurthurmusendame@gmail.com"}],"homepage":"https://github.com/aurthurm/beakblock#readme","bugs":{"url":"https://github.com/aurthurm/beakblock/issues"},"dist":{"shasum":"cb5205b4b77ca0f96ee436c6d0e673ebcabb83b6","tarball":"https://registry.npmjs.org/@amusendame/beakblock-vue/-/beakblock-vue-0.1.0.tgz","fileCount":55,"integrity":"sha512-IU9qhgvHhgoZLYUxYldy01mdnzyZkRJryt37kyWtTUBQw/fburRopAwBOuuHWuNkDogbgazubmlwYyN0BkCVwg==","signatures":[{"sig":"MEQCICVoSOwJQLKTwvK7tMA+WOJHQhLlILN0DY7ykqgts/9CAiBoLLtkgyg1LmD/7agoBauJbRi6gygE7jh9bfdXVpqwnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2845949},"main":"./dist/index.js","type":"module","_from":"file:amusendame-beakblock-vue-0.1.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","lint":"eslint src","test":"vitest run","build":"vite build","clean":"rm -rf dist","test:watch":"vitest"},"_npmUser":{"name":"amusendame","email":"aurthurmusendame@gmail.com"},"_resolved":"/tmp/300a8ce043a47714f63eaaed53720435/amusendame-beakblock-vue-0.1.0.tgz","_integrity":"sha512-IU9qhgvHhgoZLYUxYldy01mdnzyZkRJryt37kyWtTUBQw/fburRopAwBOuuHWuNkDogbgazubmlwYyN0BkCVwg==","repository":{"url":"git+https://github.com/aurthurm/beakblock.git","type":"git","directory":"packages/vue"},"_npmVersion":"11.7.0","description":"Vue bindings for BeakBlock editor","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","dependencies":{"chart.js":"^4.5.1","emoji-mart":"^5.6.0","@iconify/vue":"^5.0.0","@emoji-mart/data":"^1.2.1","@amusendame/beakblock-core":"0.1.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.26","vite":"^6.0.7","jsdom":"^25.0.1","vitest":"^2.1.8","typescript":"^5.7.2","@vue/test-utils":"^2.4.6","vite-plugin-dts":"^4.4.0"},"peerDependencies":{"vue":">=3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/beakblock-vue_0.1.0_1776513862145_0.9908376677182229","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@amusendame/beakblock-vue","version":"0.1.1","keywords":["editor","rich-text","prosemirror","block-editor","wysiwyg","notion-like","vue","vue3","typescript","text-editor"],"license":"Apache-2.0","_id":"@amusendame/beakblock-vue@0.1.1","maintainers":[{"name":"amusendame","email":"aurthurmusendame@gmail.com"}],"homepage":"https://github.com/aurthurm/beakblock#readme","bugs":{"url":"https://github.com/aurthurm/beakblock/issues"},"dist":{"shasum":"6851727db9e24bb25a392828c32eb3c379a1e9cf","tarball":"https://registry.npmjs.org/@amusendame/beakblock-vue/-/beakblock-vue-0.1.1.tgz","fileCount":55,"integrity":"sha512-23WnsdRr6eezjJqkdcU++cjTPWIB8xrHzkpjnzoBoEdYPN2P2V1399YvJVXDTF82StE9ru8N+DIu5w10PBhwPw==","signatures":[{"sig":"MEUCIEzcU9MpnfrxgUgiy0RWqdSKqllORqhLJq75J6sBE29PAiEAkJ5+8LK+fWvVzG9904ac0VJCJZSOtSkvKDmGbXP+Unw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2845949},"main":"./dist/index.js","type":"module","_from":"file:amusendame-beakblock-vue-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","lint":"eslint src","test":"vitest run","build":"vite build","clean":"rm -rf dist","test:watch":"vitest"},"_npmUser":{"name":"amusendame","email":"aurthurmusendame@gmail.com"},"_resolved":"/tmp/620fab9106e954ea36e5932156e54e93/amusendame-beakblock-vue-0.1.1.tgz","_integrity":"sha512-23WnsdRr6eezjJqkdcU++cjTPWIB8xrHzkpjnzoBoEdYPN2P2V1399YvJVXDTF82StE9ru8N+DIu5w10PBhwPw==","repository":{"url":"git+https://github.com/aurthurm/beakblock.git","type":"git","directory":"packages/vue"},"_npmVersion":"11.7.0","description":"Vue bindings for BeakBlock editor","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","dependencies":{"chart.js":"^4.5.1","emoji-mart":"^5.6.0","@iconify/vue":"^5.0.0","@emoji-mart/data":"^1.2.1","@amusendame/beakblock-core":"0.1.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.26","vite":"^6.0.7","jsdom":"^25.0.1","vitest":"^2.1.8","typescript":"^5.7.2","@vue/test-utils":"^2.4.6","vite-plugin-dts":"^4.4.0"},"peerDependencies":{"vue":">=3.5.0"},"_npmOperationalInternal":{"tmp":"tmp/beakblock-vue_0.1.1_1776521355202_0.505023855030607","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@amusendame/beakblock-vue","version":"0.1.2","description":"Vue bindings for BeakBlock editor","license":"Apache-2.0","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"keywords":["editor","rich-text","prosemirror","block-editor","wysiwyg","notion-like","vue","vue3","typescript","text-editor"],"dependencies":{"@emoji-mart/data":"^1.2.1","@iconify/vue":"^5.0.0","chart.js":"^4.5.1","emoji-mart":"^5.6.0","@amusendame/beakblock-core":"0.1.2"},"devDependencies":{"@vue/test-utils":"^2.4.6","jsdom":"^25.0.1","typescript":"^5.7.2","vite":"^6.0.7","vite-plugin-dts":"^4.4.0","vitest":"^2.1.8","vue":"^3.5.26"},"peerDependencies":{"vue":">=3.5.0"},"sideEffects":false,"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"repository":{"type":"git","url":"git+https://github.com/aurthurm/beakblock.git","directory":"packages/vue"},"homepage":"https://github.com/aurthurm/beakblock#readme","bugs":{"url":"https://github.com/aurthurm/beakblock/issues"},"scripts":{"build":"vite build","dev":"vite build --watch","lint":"eslint src","test":"vitest run","test:watch":"vitest","clean":"rm -rf dist"},"_id":"@amusendame/beakblock-vue@0.1.2","_integrity":"sha512-ngkn7KVzGB4/AwCTIaLn62JTiltS9turkqBXdZKJ6ZGJlVYwc6bNbeMzyxwVoEdlnzSokHfT33L8gy1HZShW+g==","_resolved":"/tmp/50882cd2d9245e4a4d8ac5a2ea7a81f6/amusendame-beakblock-vue-0.1.2.tgz","_from":"file:amusendame-beakblock-vue-0.1.2.tgz","_nodeVersion":"22.22.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-ngkn7KVzGB4/AwCTIaLn62JTiltS9turkqBXdZKJ6ZGJlVYwc6bNbeMzyxwVoEdlnzSokHfT33L8gy1HZShW+g==","shasum":"e8df47f0740ebf5b3b99ade775b37de0da37e559","tarball":"https://registry.npmjs.org/@amusendame/beakblock-vue/-/beakblock-vue-0.1.2.tgz","fileCount":55,"unpackedSize":2845949,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGpGJnao9FMojGSpHo3YJWwkeNxbi7aI+8dB/Kz/Gc7qAiBwr6DplrMYOFy9Km09nIfITgKQ7uhgSdq9VrfLK1PYUg=="}]},"_npmUser":{"name":"amusendame","email":"aurthurmusendame@gmail.com"},"directories":{},"maintainers":[{"name":"amusendame","email":"aurthurmusendame@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/beakblock-vue_0.1.2_1776580977614_0.8396768932819485"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-18T12:04:22.077Z","modified":"2026-04-19T06:42:57.943Z","0.1.0":"2026-04-18T12:04:22.337Z","0.1.1":"2026-04-18T14:09:15.374Z","0.1.2":"2026-04-19T06:42:57.823Z"},"bugs":{"url":"https://github.com/aurthurm/beakblock/issues"},"license":"Apache-2.0","homepage":"https://github.com/aurthurm/beakblock#readme","keywords":["editor","rich-text","prosemirror","block-editor","wysiwyg","notion-like","vue","vue3","typescript","text-editor"],"repository":{"type":"git","url":"git+https://github.com/aurthurm/beakblock.git","directory":"packages/vue"},"description":"Vue bindings for BeakBlock editor","maintainers":[{"name":"amusendame","email":"aurthurmusendame@gmail.com"}],"readme":"# @amusendame/beakblock-vue\n\nVue 3 bindings for the BeakBlock rich text editor.\n\n## Installation\n\n```bash\npnpm add @amusendame/beakblock-core @amusendame/beakblock-vue vue\n```\n\n## Quick Start\n\n```vue\n<script setup lang=\"ts\">\nimport { useBeakBlock, BeakBlockView, SlashMenu, BubbleMenu } from '@amusendame/beakblock-vue';\nimport { createChartBlockSpec } from '@amusendame/beakblock-vue';\n\nconst editor = useBeakBlock({\n  initialContent: [\n    {\n      id: '1',\n      type: 'heading',\n      props: { level: 1 },\n      content: [{ type: 'text', text: 'Hello Vue', styles: {} }],\n    },\n    {\n      id: '2',\n      type: 'paragraph',\n      props: {},\n      content: [{ type: 'text', text: 'Start editing...', styles: {} }],\n    },\n  ],\n  customBlocks: [createChartBlockSpec()],\n});\n</script>\n\n<template>\n  <BeakBlockView :editor=\"editor\" class-name=\"my-editor\" />\n  <SlashMenu :editor=\"editor\" />\n  <BubbleMenu :editor=\"editor\" />\n</template>\n```\n\n## Composables\n\n### `useBeakBlock`\n\nCreates and manages an `BeakBlockEditor` instance.\n\n```ts\nconst editor = useBeakBlock({\n  initialContent: [...],\n  editable: true,\n  autoFocus: 'end',\n  injectStyles: true,\n});\n```\n\n### `useEditorContent`\n\nSubscribe to document changes.\n\n```ts\nconst blocks = useEditorContent(editor);\n```\n\n### `useEditorSelection`\n\nSubscribe to selection changes.\n\n```ts\nconst selectedBlocks = useEditorSelection(editor);\n```\n\n### `useEditorFocus`\n\nTrack editor focus state.\n\n```ts\nconst isFocused = useEditorFocus(editor);\n```\n\n### `useCustomSlashMenuItems`\n\nBuild slash menu items from custom Vue blocks.\n\n```ts\nconst customSlashItems = useCustomSlashMenuItems(editor, customBlocks);\n```\n\n## Comments\n\nInline comments use **`CommentStore`** and **`createCommentPlugin`** from `@amusendame/beakblock-core`, plus Vue components:\n\n- **`CommentRail`** — marker rail and flyouts around the editor (wraps `BeakBlockView` in the default slot).\n- **`CommentModal`** — modal to add a thread from the current selection and manage overlapping threads.\n\nHook **`BubbleMenu`** with `@comment` to open the modal. On every editor transaction with a document change, call **`store.mapAnchors(transaction.mapping)`** so highlights stay aligned (see guide).\n\nFull API, anchoring, persistence, and troubleshooting: **[Comments guide](../../docs/comments.md)**.\n\nExample: [`examples/nuxt-vue/components/ComplianceSectionEditor.vue`](../examples/nuxt-vue/components/ComplianceSectionEditor.vue) — also wires **section approvals**, **approval history**, **post-approval read-only lock** for authors, and lives inside the broader compliance workspace (**[Compliance workflow](../../docs/compliance-demo.md)**).\n\n## Components\n\n### `BeakBlockView`\n\nRenders the editor view.\n\n```vue\n<BeakBlockView\n  :editor=\"editor\"\n  class-name=\"my-editor\"\n  tag=\"section\"\n/>\n```\n\nThe component exposes `container` and `editor` via `ref`.\n\n### `SlashMenu`\n\nCommand palette triggered by `/`.\n\n```vue\n<SlashMenu :editor=\"editor\" />\n```\n\nSupports `items`, `customItems`, `itemOrder`, `hideItems`, and `renderItem`.\n\n### `createChartBlockSpec`\n\nAdds a Chart.js-backed block with editable data and inline slash menu support.\n\n```ts\nimport { createChartBlockSpec, useCustomSlashMenuItems, useBeakBlock } from '@amusendame/beakblock-vue';\n\nconst customBlocks = [createChartBlockSpec()];\nconst editor = useBeakBlock({\n  customBlocks,\n});\nconst customSlashItems = useCustomSlashMenuItems(editor, customBlocks);\n```\n\nPass `customSlashItems` into `<SlashMenu :custom-items=\"customSlashItems\" />` so the chart command appears in the `/` menu.\n\nThe chart block exposes a chart editor modal and serializes chart data through the document JSON.\n\n### `BubbleMenu`\n\nFloating formatting toolbar.\n\n```vue\n<BubbleMenu :editor=\"editor\" />\n```\n\nSupports `customItems`, `itemOrder`, `hideItems`, and `children`.\n\n### `ColorPicker`\n\nColor picker for text and background colors.\n\n```vue\n<ColorPicker\n  :editor=\"editor\"\n  :current-text-color=\"textColor\"\n  :current-background-color=\"backgroundColor\"\n/>\n```\n\n### `TableMenu`\n\nTable editing menu for rows, columns, and delete actions.\n\n```vue\n<TableMenu :editor=\"editor\" />\n```\n\n### `TableHandles`\n\nRow and column handles for table manipulation.\n\n```vue\n<TableHandles :editor=\"editor\" />\n```\n\n### `MediaMenu`\n\nMedia block menu for image and embed controls.\n\n```vue\n<MediaMenu :editor=\"editor\" />\n```\n\n### `LinkPopover`\n\nLink editing popover for inline text selections.\n\n```vue\n<LinkPopover\n  :editor=\"editor\"\n  :current-url=\"currentUrl\"\n  :position=\"{ left: 0, top: 0 }\"\n  :on-close=\"closePopover\"\n/>\n```\n\n## BubbleMenu Customization\n\nThe `BubbleMenu` supports the same item ordering and custom item model as the React package.\n\n### Props\n\n```ts\ninterface BubbleMenuProps {\n  editor: BeakBlockEditor | null;\n  customItems?: BubbleMenuItem[];\n  itemOrder?: string[];\n  hideItems?: string[];\n  className?: string;\n  children?: (props: { editor: BeakBlockEditor; state: BubbleMenuState }) => VNodeChild;\n}\n```\n\n### Default Item IDs\n\n- Block type: `blockType`\n- Alignment: `alignLeft`, `alignCenter`, `alignRight`\n- Formatting: `bold`, `italic`, `underline`, `strikethrough`\n- Style: `code`, `link`, `color`\n\n### Example: Add a Custom Button\n\n```vue\n<script setup lang=\"ts\">\nimport { BubbleMenu } from '@amusendame/beakblock-vue';\n\nconst translateButton = {\n  id: 'translate',\n  label: 'Translate',\n  icon: 'Translate',\n  action: async (editor, state) => {\n    const text = editor.pm.state.doc.textBetween(state.from, state.to);\n    const translated = await translateAPI(text);\n    console.log(translated);\n  },\n};\n</script>\n\n<template>\n  <BubbleMenu\n    :editor=\"editor\"\n    :custom-items=\"[translateButton]\"\n  />\n</template>\n```\n\n### Example: Reorder Items\n\n```vue\n<BubbleMenu\n  :editor=\"editor\"\n  :item-order=\"['bold', 'italic', 'underline', '---', 'link', 'color', '---', 'translate']\"\n/>\n```\n\n### Example: Minimal Toolbar\n\n```vue\n<BubbleMenu\n  :editor=\"editor\"\n  :item-order=\"['bold', 'italic', '---', 'link']\"\n/>\n```\n\n### Example: Hide Items\n\n```vue\n<BubbleMenu\n  :editor=\"editor\"\n  :hide-items=\"['strikethrough', 'code', 'alignLeft', 'alignCenter', 'alignRight']\"\n/>\n```\n\n## SlashMenu Customization\n\nThe `SlashMenu` supports customization similar to `BubbleMenu`.\n\n### Props\n\n```ts\ninterface SlashMenuProps {\n  editor: BeakBlockEditor | null;\n  items?: SlashMenuItem[];\n  customItems?: SlashMenuItem[];\n  itemOrder?: string[];\n  hideItems?: string[];\n  renderItem?: (item: SlashMenuItem, isSelected: boolean) => VNodeChild;\n  className?: string;\n}\n```\n\n### Default Item IDs\n\n- Text: `paragraph`, `heading`\n- Lists: `bulletList`, `numberedList`, `checkList`\n- Blocks: `blockquote`, `codeBlock`, `callout`, `divider`\n- Tables: `table`\n- Media: `image`, `video`, `audio`, `file`\n\n### Example: Add Custom Items\n\n```vue\n<script setup lang=\"ts\">\nimport { SlashMenu } from '@amusendame/beakblock-vue';\n\nconst customItems = [\n  {\n    id: 'emoji',\n    title: 'Emoji',\n    description: 'Insert an emoji picker',\n    icon: '😀',\n    action: (editor) => {\n      console.log('open emoji picker', editor);\n    },\n  },\n  {\n    id: 'template',\n    title: 'Template',\n    description: 'Insert a predefined template',\n    icon: '📄',\n    action: (editor) => {\n      console.log('insert template', editor);\n    },\n  },\n];\n</script>\n\n<template>\n  <SlashMenu\n    :editor=\"editor\"\n    :custom-items=\"customItems\"\n  />\n</template>\n```\n\n### Example: Custom Order\n\n```vue\n<SlashMenu\n  :editor=\"editor\"\n  :item-order=\"['paragraph', 'heading', 'bulletList', 'emoji', 'template']\"\n/>\n```\n\n### Example: Hide Items\n\n```vue\n<SlashMenu\n  :editor=\"editor\"\n  :hide-items=\"['table', 'video', 'audio', 'file']\"\n/>\n```\n\n## ColorPicker Customization\n\nThe `ColorPicker` component accepts custom palettes.\n\n### Props\n\n```ts\ninterface ColorPickerProps {\n  editor: BeakBlockEditor;\n  currentTextColor: string | null;\n  currentBackgroundColor: string | null;\n  textColors?: ColorOption[];\n  backgroundColors?: ColorOption[];\n  textColorLabel?: string;\n  backgroundColorLabel?: string;\n  onClose?: () => void;\n}\n```\n\n### Default Palettes\n\n```ts\nimport { DEFAULT_TEXT_COLORS, DEFAULT_BACKGROUND_COLORS } from '@amusendame/beakblock-vue';\n```\n\n### Example: Brand Color Palette\n\n```vue\n<script setup lang=\"ts\">\nimport { ColorPicker } from '@amusendame/beakblock-vue';\n\nconst brandTextColors = [\n  { value: '', label: 'Default' },\n  { value: '#1a1a1a', label: 'Black' },\n  { value: '#0066cc', label: 'Primary' },\n  { value: '#00994d', label: 'Success' },\n  { value: '#cc3300', label: 'Error' },\n];\n\nconst brandBackgroundColors = [\n  { value: '', label: 'None' },\n  { value: '#e6f2ff', label: 'Blue' },\n  { value: '#e6ffe6', label: 'Green' },\n  { value: '#ffe6e6', label: 'Red' },\n];\n</script>\n\n<template>\n  <ColorPicker\n    :editor=\"editor\"\n    :current-text-color=\"textColor\"\n    :current-background-color=\"bgColor\"\n    :text-colors=\"brandTextColors\"\n    :background-colors=\"brandBackgroundColors\"\n    text-color-label=\"Text Color\"\n    background-color-label=\"Highlight\"\n  />\n</template>\n```\n\n## Accessing ProseMirror\n\nThe editor instance exposes the public ProseMirror surface directly:\n\n```vue\n<script setup lang=\"ts\">\nimport { useBeakBlock, BeakBlockView } from '@amusendame/beakblock-vue';\n\nconst editor = useBeakBlock({});\n\nconst handleBold = () => {\n  editor.value?.toggleBold();\n};\n\nconst handleCustomAction = () => {\n  const currentEditor = editor.value;\n  if (!currentEditor) return;\n\n  const tr = currentEditor.pm.createTransaction();\n  tr.insertText('Custom text');\n  currentEditor.pm.dispatch(tr);\n};\n</script>\n\n<template>\n  <button type=\"button\" @click=\"handleBold\">Bold</button>\n  <button type=\"button\" @click=\"handleCustomAction\">Insert</button>\n  <BeakBlockView :editor=\"editor\" />\n</template>\n```\n\n## Example Apps\n\n- [`examples/vite-vue`](../../examples/vite-vue) - Vite + Vue demo\n- [`examples/nuxt-vue`](../../examples/nuxt-vue) - Nuxt + Vue demo\n","readmeFilename":"README.md"}