@bloklabs/vue 1.2.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @bloklabs/vue
2
+
3
+ The Vue 3 block editor bindings for [Blok](https://blokeditor.com) — a headless, Notion-like rich text editor whose content is JSON blocks, not HTML.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @bloklabs/vue @bloklabs/core
9
+ ```
10
+
11
+ `@bloklabs/core` and `vue` are peer dependencies.
12
+
13
+ ## Usage
14
+
15
+ `<BlokEditor>` is the all-in-one component: it mounts the editor, manages its lifecycle, and takes every editor config option as a prop.
16
+
17
+ ```vue
18
+ <script setup lang="ts">
19
+ import { BlokEditor } from '@bloklabs/vue';
20
+ import { Header, Paragraph, List } from '@bloklabs/core/tools';
21
+
22
+ const tools = {
23
+ paragraph: Paragraph,
24
+ header: { class: Header, placeholder: 'Enter a heading' },
25
+ list: List,
26
+ };
27
+ </script>
28
+
29
+ <template>
30
+ <BlokEditor :tools="tools" />
31
+ </template>
32
+ ```
33
+
34
+ ## Saving
35
+
36
+ The `save` emit fires with the latest content on every change, so you never have to call `save()` by hand.
37
+
38
+ ```vue
39
+ <script setup lang="ts">
40
+ import { ref } from 'vue';
41
+ import { BlokEditor } from '@bloklabs/vue';
42
+ import type { OutputData } from '@bloklabs/core';
43
+
44
+ const data = ref<OutputData>();
45
+ </script>
46
+
47
+ <template>
48
+ <BlokEditor @save="(d: OutputData) => (data = d)" />
49
+ <pre>{{ data?.blocks }}</pre>
50
+ </template>
51
+ ```
52
+
53
+ ## Also exported
54
+
55
+ - `useBlok(config, recreateKey?)` — the composable behind the component, returns a `Ref<Blok | null>`.
56
+ - `BlokContent` — the mount-point element, if you want to wire the composable yourself.
57
+ - `useBlocks(editor)` — a reactive snapshot of the block tree plus a manipulation API.
58
+ - `createVueBlock` — author block tools as Vue components.
59
+ - `provideBlok` / `useBlokDefaults` — share default editor config through provide/inject.
60
+
61
+ ## Docs
62
+
63
+ - [Quick start](https://blokeditor.com/docs/quick-start?framework=vue)
64
+ - [`BlokEditor` reference](https://blokeditor.com/docs/blok-editor?framework=vue)
65
+ - [`useBlocks` reference](https://blokeditor.com/docs/use-blocks?framework=vue)
66
+
67
+ Licensed under Apache-2.0.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`),t=require(`@bloklabs/core`),n=require(`@bloklabs/core/adapters`);var r=new WeakMap;function i(e,t){r.set(e,t)}function a(e){return r.get(e)}function o(e){r.delete(e)}function s(e){"@babel/helpers - typeof";return s=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},s(e)}function c(e,t){if(s(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(s(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function l(e){var t=c(e,`string`);return s(t)==`symbol`?t:t+``}function u(e,t,n){return(t=l(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function d(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function f(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?d(Object(n),!0).forEach(function(t){u(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):d(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var p=Symbol(`BLOK_DEFAULT_CONFIG`);function m(t){(0,e.provide)(p,t)}function h(){return(0,e.inject)(p,{})}function g(e,t){if(Object.keys(e).length===0)return t;let n=f({},e);for(let e of Object.keys(t)){let r=t[e];r!==void 0&&(n[e]=r)}return(e.tools!==void 0||t.tools!==void 0)&&(n.tools=f(f({},e.tools),t.tools)),n}var _=`__blokPortalRegistry`,v=()=>{let t=(0,e.reactive)(new Map);return{entries:t,register(n,r){t.set(n,(0,e.markRaw)(r))},unregister(e){t.delete(e)},setProps(e,n){let r=t.get(e);r!==void 0&&Object.assign(r.props,n)}}},y=new WeakMap;function b(e,t){y.set(e,t)}function x(e){return y.get(e)}function S(e){y.delete(e)}var C=(e,t)=>{if(typeof e!=`object`||!e)return e;let n={};for(let[i,a]of Object.entries(e)){var r;let e=typeof a==`function`?a:a==null?void 0:a.class;if(!(typeof e==`function`&&e.__isBlokVueBlock===!0)){n[i]=a;continue}let o=typeof a==`function`?{class:a}:f({},a);o.config=f(f({},(r=o.config)==null?{}:r),{},{[_]:t}),n[i]=o}return n};function w(r,a){let s=(0,e.shallowRef)(null),c=(0,e.inject)(p,{}),l=()=>g(c,(0,e.toValue)(r)),u={current:null,holder:null,lastRenderedData:l().data,seededEditor:null,renderChain:Promise.resolve()},d=()=>{let t=f({},g((0,e.toRaw)(c),(0,e.toRaw)((0,e.toValue)(r))));return delete t.holder,t.data!==void 0&&(t.data=(0,e.toRaw)(t.data)),t},m=()=>{if(u.current!==null){o(u.current),S(u.current);try{u.current.destroy()}catch(e){}}u.current=null,u.holder=null,s.value=null},h=()=>{let e=document.createElement(`div`);u.holder=e;let n=d(),r=v();n.tools!==void 0&&(n.tools=C(n.tools,r)),typeof n.onSave==`function`&&(n.onSave=(...e)=>{var t,n;u.lastRenderedData=e[0],(t=(n=l()).onSave)==null||t.call(n,...e)});let a=new t.Blok(f(f({},n),{},{holder:e}));u.current=a,i(a,e),b(a,r),a.isReady.then(()=>{u.current===a&&(s.value=a)}).catch(()=>{u.current===a&&m()})};return(0,e.watch)([s,()=>(0,n.normalizeReadOnlyConfig)(l().readOnly).enabled],([e,t])=>{e&&e.readOnly.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().theme],([e,t])=>{e&&t!==void 0&&e.theme.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().width],([e,t])=>{e&&t!==void 0&&e.width.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().placeholder],([e,t])=>{e&&t!==void 0&&e.placeholder.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().autofocus],([e,t])=>{e&&t&&e.focus()},{immediate:!0}),(0,e.watch)([s,()=>l().data],([t,r])=>{if(!(!t||r===void 0)){if(u.seededEditor!==t){u.seededEditor=t,u.lastRenderedData=r;return}(0,n.deepEqual)(r,u.lastRenderedData)||(u.lastRenderedData=r,u.renderChain=u.renderChain.catch(()=>void 0).then(()=>t.render((0,e.toRaw)(r))))}},{immediate:!0}),a!==void 0&&(0,e.watch)(()=>(0,e.toValue)(a),()=>{m(),h()}),(0,e.onMounted)(h),(0,e.onBeforeUnmount)(m),s}var T=`block changed`;function E(t){let r=(0,e.shallowRef)(0),i=()=>{let n=(0,e.toValue)(t);return n===null?null:(0,e.toRaw)(n)},a=()=>{r.value},o=(0,e.shallowRef)(n.EMPTY_API),s={editor:null,handler:null},c=()=>{s.editor!==null&&s.handler!==null&&s.editor.off(T,s.handler),s.editor=null,s.handler=null};return(0,e.watch)(()=>i(),e=>{if(c(),r.value+=1,e===null){o.value=n.EMPTY_API;return}let t=()=>{r.value+=1};e.on(T,t),s.editor=e,s.handler=t,o.value=(0,n.createBlocksApiForEditor)(e,a)},{immediate:!0}),(0,e.onScopeDispose)(c),{getById:e=>o.value.getById(e),getChildren:e=>o.value.getChildren(e),insert:e=>o.value.insert(e),insertMany:e=>o.value.insertMany(e),insertTree:e=>o.value.insertTree(e),insertMarkdown:(e,t)=>o.value.insertMarkdown(e,t),exportMarkdown:()=>o.value.exportMarkdown(),move:(e,t)=>o.value.move(e,t),nest:(e,t)=>o.value.nest(e,t),unnest:e=>o.value.unnest(e),remove:e=>o.value.remove(e),update:(e,t,n)=>o.value.update(e,t,n),convert:(e,t,n,r)=>o.value.convert(e,t,n,r),transact:e=>o.value.transact(e),transactWithoutCapture:e=>o.value.transactWithoutCapture(e),getBlocksCount:()=>o.value.getBlocksCount(),getCurrentBlockIndex:()=>o.value.getCurrentBlockIndex(),getBlockByIndex:e=>o.value.getBlockByIndex(e),getBlockByElement:e=>o.value.getBlockByElement(e),getBlockData:e=>o.value.getBlockData(e),getBlockIndex:e=>o.value.getBlockIndex(e),composeBlockData:e=>o.value.composeBlockData(e),renderFromHTML:e=>o.value.renderFromHTML(e),insertOutputData:(e,t)=>o.value.insertOutputData(e,t),splitBlock:(e,t,n,r,i)=>o.value.splitBlock(e,t,n,r,i),insertInsideParent:(e,t,n)=>o.value.insertInsideParent(e,t,n),render:e=>o.value.render(e),clear:()=>o.value.clear(),isSyncingFromYjs:()=>o.value.isSyncingFromYjs()}}var D=(0,e.defineComponent)({name:`BlockErrorBoundary`,setup(t,{slots:n}){return(0,e.onErrorCaptured)(()=>!1),()=>{var e;return(e=n.default)==null?void 0:e.call(n)}}}),O=(0,e.defineComponent)({name:`BlockPortalHost`,props:{registry:{type:Object,required:!0}},setup(t){return()=>(0,e.h)(e.Fragment,Array.from(t.registry.entries.entries()).map(([t,n])=>(0,e.h)(e.Teleport,{key:t,to:n.hostEl},[(0,e.h)(D,null,{default:()=>(0,e.h)(n.component,n.props)})])))}}),k=(0,e.defineComponent)({name:`BlokContent`,props:{editor:{type:Object,default:null}},setup(t){let n=(0,e.ref)(null),r=t=>{if(n.value===null||t===null)return;let r=a((0,e.toRaw)(t));r!==void 0&&n.value.appendChild(r)},i=t=>{var n;t!==null&&((n=a((0,e.toRaw)(t)))==null||n.remove())};return(0,e.onMounted)(()=>{r(t.editor)}),(0,e.watch)(()=>t.editor,(e,t)=>{i(t==null?null:t),r(e)}),(0,e.onBeforeUnmount)(()=>{i(t.editor)}),()=>{let r=t.editor,i=r===null?void 0:x((0,e.toRaw)(r));return(0,e.h)(`div`,{ref:n},i===void 0?[]:[(0,e.h)(O,{registry:i})])}}}),A=`autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter`.split(`.`),j=(0,e.defineComponent)({name:`BlokEditor`,inheritAttrs:!1,props:{autofocus:{type:Boolean,default:void 0},defaultBlock:{type:String,default:void 0},dataModel:{type:String,default:void 0},placeholder:{type:[String,Boolean],default:void 0},sanitizer:{type:Object,default:void 0},hideToolbar:{type:Boolean,default:void 0},maxHistoryLength:{type:Number,default:void 0},historyDebounceTime:{type:Number,default:void 0},newGroupDelay:{type:Number,default:void 0},globalUndoRedo:{type:Boolean,default:void 0},tools:{type:Object,default:void 0},data:{type:Object,default:void 0},minHeight:{type:Number,default:void 0},logLevel:{type:String,default:void 0},readOnly:{type:Boolean,default:void 0},i18n:{type:Object,default:void 0},link:{type:Object,default:void 0},linkPaste:{type:Object,default:void 0},inlineToolbar:{type:[Array,Boolean],default:void 0},tunes:{type:Array,default:void 0},style:{type:Object,default:void 0},theme:{type:String,default:void 0},scrollToBlock:{type:Object,default:void 0},user:{type:Object,default:void 0},resolveUser:{type:Function,default:void 0},notifierPosition:{type:String,default:void 0},notifier:{type:Function,default:void 0},width:{type:String,default:void 0},onBeforeRender:{type:Function,default:void 0},onBeforePaste:{type:Function,default:void 0},onEnter:{type:Function,default:void 0},recreateKey:{type:null}},emits:{ready:e=>!0,change:e=>!0,save:e=>!0,"update:data":e=>!0,"after-render":e=>!0,"theme-change":e=>!0,"blocks-rendered":e=>!0,"block-rendered":e=>!0},setup(t,{emit:n,expose:r,attrs:i}){let a=(0,e.getCurrentInstance)(),o=e=>{let t=a==null?void 0:a.vnode.props;return t!=null&&e in t},s=()=>{let e={};for(let n of A){let r=t[n];r!==void 0&&(e[n]=r)}return o(`onChange`)&&(e.onChange=(e,t)=>{n(`change`,{api:e,event:t})}),(o(`onSave`)||o(`onUpdate:data`))&&(e.onSave=e=>{n(`update:data`,e),n(`save`,e)}),o(`onAfterRender`)&&(e.onAfterRender=e=>{n(`after-render`,e)}),o(`onThemeChange`)&&(e.onThemeChange=e=>{n(`theme-change`,e)}),e},c=w(()=>s(),()=>t.recreateKey);(0,e.watch)(c,(e,t,r)=>{if(e===null)return;let i=[];if(o(`onBlocksRendered`)){let t=e=>n(`blocks-rendered`,e);e.on(`blocks:rendered`,t),i.push([`blocks:rendered`,t])}if(o(`onBlockRendered`)){let t=e=>n(`block-rendered`,e);e.on(`block:rendered`,t),i.push([`block:rendered`,t])}r(()=>{for(let[t,n]of i)e.off(t,n)})});let l={last:null};return(0,e.watch)(c,e=>{e!==null&&e!==l.last&&(l.last=e,n(`ready`,e))}),r({instance:(0,e.computed)(()=>c.value),save:()=>{var e;return(e=c.value)==null?void 0:e.save()},focus:e=>{var t;(t=c.value)==null||t.focus(e)},render:e=>{var t;return(t=c.value)==null?void 0:t.render(e)}}),()=>(0,e.h)(k,f({editor:c.value},i))}});function M(t){var r;let i=(0,e.defineComponent)({name:`VueBlock(${t.type})`,props:{ctx:{type:Object,required:!0}},setup(e){return t.setup(e.ctx)}});return r=class{static get toolbox(){return t.toolbox}static get isReadOnlySupported(){return!0}constructor(r){var i,a;this.hostEl=null,this.pendingDispatch=!1,this.commit=e=>{let r=(0,n.fillDefaults)(t.propSchema,f(f({},this.mirror),e));(0,n.deepEqual)(r,this.mirror)||(this.mirror=r,this.lastRendered=r,this.dataRef.value=r,this.flushDispatch())},this.blockApi=r.block;let o=(i=r.config)==null?{}:i;this.registry=o[_];let s=r.api;this.pointerDrag=()=>{var e;return(s==null||(e=s.blocks)==null?void 0:e.isPointerDragActive)===!0},this.mirror=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)((a=r.data)==null?{}:a)),this.lastRendered=this.mirror,this.dataRef=(0,e.shallowRef)(this.mirror),this.readOnlyRef=(0,e.shallowRef)(r.readOnly);let c=this.blockApi;this.childrenComponent=(0,e.defineComponent)({name:`VueBlockChildren(${t.type})`,setup(){let t=(0,e.ref)(null),r=()=>{t.value!==null&&(0,n.mountChildBlocks)(t.value,c.getChildren())};return(0,e.onMounted)(r),(0,e.onUpdated)(r),()=>(0,e.h)(`div`,{ref:t,[n.DATA_ATTR.nestedBlocks]:``})}})}render(){var e;let t=document.createElement(`div`);t.setAttribute(`data-blok-mutation-free`,`true`),this.hostEl=t;let n={data:this.dataRef,commit:this.commit,block:this.blockApi,readOnly:this.readOnlyRef,BlockChildren:this.childrenComponent};return(e=this.registry)==null||e.register(this.blockApi.id,{hostEl:t,component:i,props:{ctx:n}}),t}rendered(){var e;(e=t.onRendered)==null||e.call(t,this.blockApi)}save(){return this.mirror}async setData(r){var i=this;let a=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)(r==null?{}:r));return(0,n.deepEqual)(a,i.lastRendered)?!0:(i.mirror=a,i.lastRendered=a,i.dataRef.value=a,await(0,e.nextTick)(),!0)}setReadOnly(e){this.readOnlyRef.value=e}moved(){var e;(e=t.onMoved)==null||e.call(t,this.blockApi)}removed(){var e,n;(e=this.registry)==null||e.unregister(this.blockApi.id),(n=t.onRemoved)==null||n.call(t,this.blockApi)}destroy(){var e;(e=this.registry)==null||e.unregister(this.blockApi.id)}flushDispatch(){if(!this.pointerDrag()){this.pendingDispatch=!1,this.blockApi.dispatchChange();return}if(this.pendingDispatch)return;this.pendingDispatch=!0;let e=()=>{if(this.pointerDrag()){requestAnimationFrame(e);return}this.pendingDispatch=!1,this.blockApi.dispatchChange()};requestAnimationFrame(e)}},r.__isBlokVueBlock=!0,r}exports.BLOK_DEFAULT_CONFIG=p,exports.BlokContent=k,exports.BlokEditor=j,exports.createVueBlock=M,exports.provideBlok=m,exports.useBlocks=E,exports.useBlok=w,exports.useBlokDefaults=h;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("vue"),t=require("@bloklabs/core"),n=require("@bloklabs/core/adapters");var r=new WeakMap;function i(e,t){r.set(e,t)}function a(e){return r.get(e)}function o(e){r.delete(e)}function s(e){"@babel/helpers - typeof";return s=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},s(e)}function c(e,t){if(s(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(s(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function l(e){var t=c(e,`string`);return s(t)==`symbol`?t:t+``}function u(e,t,n){return(t=l(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function d(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function f(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?d(Object(n),!0).forEach(function(t){u(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):d(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var p=Symbol(`BLOK_DEFAULT_CONFIG`);function m(t){(0,e.provide)(p,t)}function h(){return(0,e.inject)(p,{})}function g(e,t){if(Object.keys(e).length===0)return t;let n=f({},e);for(let e of Object.keys(t)){let r=t[e];r!==void 0&&(n[e]=r)}return(e.tools!==void 0||t.tools!==void 0)&&(n.tools=f(f({},e.tools),t.tools)),n}var _=`__blokPortalRegistry`,v=()=>{let t=(0,e.reactive)(new Map);return{entries:t,register(n,r){t.set(n,(0,e.markRaw)(r))},unregister(e){t.delete(e)},setProps(e,n){let r=t.get(e);r!==void 0&&Object.assign(r.props,n)}}},y=new WeakMap;function b(e,t){y.set(e,t)}function x(e){return y.get(e)}function S(e){y.delete(e)}var C=(e,t)=>{if(typeof e!=`object`||!e)return e;let n={};for(let[i,a]of Object.entries(e)){var r;let e=typeof a==`function`?a:a==null?void 0:a.class;if(!(typeof e==`function`&&e.__isBlokVueBlock===!0)){n[i]=a;continue}let o=typeof a==`function`?{class:a}:f({},a);o.config=f(f({},(r=o.config)==null?{}:r),{},{[_]:t}),n[i]=o}return n};function w(r,a){let s=(0,e.shallowRef)(null),c=(0,e.inject)(p,{}),l=()=>g(c,(0,e.toValue)(r)),u={current:null,holder:null,lastRenderedData:l().data,seededEditor:null,renderChain:Promise.resolve()},d=()=>{let t=f({},g((0,e.toRaw)(c),(0,e.toRaw)((0,e.toValue)(r))));return delete t.holder,t.data!==void 0&&(t.data=(0,e.toRaw)(t.data)),t},m=()=>{if(u.current!==null){o(u.current),S(u.current);try{u.current.destroy()}catch(e){}}u.current=null,u.holder=null,s.value=null},h=()=>{let e=document.createElement(`div`);u.holder=e;let n=d(),r=v();n.tools!==void 0&&(n.tools=C(n.tools,r)),typeof n.onSave==`function`&&(n.onSave=(...e)=>{var t,n;u.lastRenderedData=e[0],(t=(n=l()).onSave)==null||t.call(n,...e)});let a=new t.Blok(f(f({},n),{},{holder:e}));u.current=a,i(a,e),b(a,r),a.isReady.then(()=>{u.current===a&&(s.value=a)}).catch(()=>{u.current===a&&m()})};(0,e.watch)([s,()=>(0,n.normalizeReadOnlyConfig)(l().readOnly).enabled,()=>(0,n.normalizeReadOnlyConfig)(l().readOnly).hideControls,()=>typeof l().readOnly==`object`],([e,t,n,r])=>{e&&(r?e.readOnly.set(t,{hideControls:n}):e.readOnly.set(t))},{immediate:!0}),(0,e.watch)([s,()=>l().hideToolbar],([e,t])=>{e&&e.toolbar.setHidden(!!t)},{immediate:!0}),(0,e.watch)([s,()=>l().theme],([e,t])=>{e&&t!==void 0&&e.theme.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().width],([e,t])=>{e&&t!==void 0&&e.width.set(t)},{immediate:!0}),(0,e.watch)([s,()=>l().placeholder],([e,t])=>{e&&t!==void 0&&e.placeholder.set(t)},{immediate:!0});let _={value:void 0};(0,e.watch)([s,()=>{var e;return(e=l().style)==null?void 0:e.tokens}],([e,t])=>{!e||t===void 0||(0,n.deepEqual)(t,_.value)||(_.value=f({},t),e.tokens.set(t))},{immediate:!0,deep:!0});let y={value:l().i18n};(0,e.watch)([s,()=>l().i18n],([e,t])=>{if(!e||t===void 0||(0,n.deepEqual)(t,y.value))return;y.value=f({},t);let{locale:r,messages:i,direction:a}=t;e.i18n.update(f(f(f({},r===void 0?{}:{locale:r}),i===void 0?{}:{messages:i}),a===void 0?{}:{direction:a}))},{immediate:!0,deep:!0});let x={editor:null,value:void 0};return(0,e.watch)([s,()=>l().inlineToolbar],([e,t])=>{if(!e||t===void 0||x.editor===e&&(0,n.deepEqual)(t,x.value))return;let r=Array.isArray(t)?[...t]:t;x.editor=e,x.value=r,e.tools.setInlineToolbar(r)},{immediate:!0,deep:!0}),(0,e.watch)([s,()=>l().autofocus],([e,t])=>{e&&t&&e.focus()},{immediate:!0}),(0,e.watch)([s,()=>l().data],([t,r])=>{if(!(!t||r===void 0)){if(u.seededEditor!==t){u.seededEditor=t,u.lastRenderedData=r;return}(0,n.deepEqual)(r,u.lastRenderedData)||(u.lastRenderedData=r,u.renderChain=u.renderChain.catch(()=>void 0).then(()=>t.render((0,e.toRaw)(r))))}},{immediate:!0}),a!==void 0&&(0,e.watch)(()=>(0,e.toValue)(a),()=>{m(),h()}),(0,e.onMounted)(h),(0,e.onBeforeUnmount)(m),s}var T=`block changed`;function E(t){let r=(0,e.shallowRef)(0),i=()=>{let n=(0,e.toValue)(t);return n===null?null:(0,e.toRaw)(n)},a=()=>{r.value},o=(0,e.shallowRef)(n.EMPTY_API),s={editor:null,handler:null},c=()=>{s.editor!==null&&s.handler!==null&&s.editor.off(T,s.handler),s.editor=null,s.handler=null};return(0,e.watch)(()=>i(),e=>{if(c(),r.value+=1,e===null){o.value=n.EMPTY_API;return}let t=()=>{r.value+=1};e.on(T,t),s.editor=e,s.handler=t,o.value=(0,n.createBlocksApiForEditor)(e,a)},{immediate:!0}),(0,e.onScopeDispose)(c),{getById:e=>o.value.getById(e),getChildren:e=>o.value.getChildren(e),insert:e=>o.value.insert(e),insertMany:e=>o.value.insertMany(e),insertTree:e=>o.value.insertTree(e),insertMarkdown:(e,t)=>o.value.insertMarkdown(e,t),exportMarkdown:()=>o.value.exportMarkdown(),move:(e,t)=>o.value.move(e,t),nest:(e,t)=>o.value.nest(e,t),unnest:e=>o.value.unnest(e),remove:e=>o.value.remove(e),update:(e,t,n)=>o.value.update(e,t,n),convert:(e,t,n,r)=>o.value.convert(e,t,n,r),transact:e=>o.value.transact(e),transactWithoutCapture:e=>o.value.transactWithoutCapture(e),getBlocksCount:()=>o.value.getBlocksCount(),getCurrentBlockIndex:()=>o.value.getCurrentBlockIndex(),getBlockByIndex:e=>o.value.getBlockByIndex(e),getBlockByElement:e=>o.value.getBlockByElement(e),getBlockData:e=>o.value.getBlockData(e),getBlockIndex:e=>o.value.getBlockIndex(e),composeBlockData:e=>o.value.composeBlockData(e),renderFromHTML:e=>o.value.renderFromHTML(e),insertOutputData:(e,t)=>o.value.insertOutputData(e,t),splitBlock:(e,t,n,r,i)=>o.value.splitBlock(e,t,n,r,i),insertInsideParent:(e,t,n)=>o.value.insertInsideParent(e,t,n),render:e=>o.value.render(e),clear:()=>o.value.clear(),isSyncingFromYjs:()=>o.value.isSyncingFromYjs()}}function D(n={}){let{within:r,settleOn:i}=n,a=(0,e.shallowRef)(!1),o=()=>{var n;let o=r===void 0||(n=(0,e.toValue)(r))==null?null:n;a.value=r!==void 0&&o===null?!1:t.Blok.readyState({within:o,settleOn:i}).ready};return(0,e.onScopeDispose)(t.Blok.subscribeReady(o)),(0,e.onMounted)(o),a}var O=(0,e.defineComponent)({name:`BlockErrorBoundary`,setup(t,{slots:n}){return(0,e.onErrorCaptured)(()=>!1),()=>{var e;return(e=n.default)==null?void 0:e.call(n)}}}),k=(0,e.defineComponent)({name:`BlockPortalHost`,props:{registry:{type:Object,required:!0}},setup(t){return()=>(0,e.h)(e.Fragment,Array.from(t.registry.entries.entries()).map(([t,n])=>(0,e.h)(e.Teleport,{key:t,to:n.hostEl},[(0,e.h)(O,null,{default:()=>(0,e.h)(n.component,n.props)})])))}}),A=(0,e.defineComponent)({name:`BlokContent`,props:{editor:{type:Object,default:null}},setup(t){let n=(0,e.ref)(null),r=t=>{if(n.value===null||t===null)return;let r=a((0,e.toRaw)(t));r!==void 0&&n.value.appendChild(r)},i=t=>{var n;t!==null&&((n=a((0,e.toRaw)(t)))==null||n.remove())};return(0,e.onMounted)(()=>{r(t.editor)}),(0,e.watch)(()=>t.editor,(e,t)=>{i(t==null?null:t),r(e)}),(0,e.onBeforeUnmount)(()=>{i(t.editor)}),()=>{let r=t.editor,i=r===null?void 0:x((0,e.toRaw)(r));return(0,e.h)(`div`,{ref:n},i===void 0?[]:[(0,e.h)(k,{registry:i})])}}}),j=`autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter`.split(`.`),M=(0,e.defineComponent)({name:`BlokEditor`,inheritAttrs:!1,props:{autofocus:{type:Boolean,default:void 0},defaultBlock:{type:String,default:void 0},dataModel:{type:String,default:void 0},placeholder:{type:[String,Boolean],default:void 0},sanitizer:{type:Object,default:void 0},hideToolbar:{type:Boolean,default:void 0},maxHistoryLength:{type:Number,default:void 0},historyDebounceTime:{type:Number,default:void 0},newGroupDelay:{type:Number,default:void 0},globalUndoRedo:{type:Boolean,default:void 0},tools:{type:Object,default:void 0},data:{type:Object,default:void 0},minHeight:{type:Number,default:void 0},logLevel:{type:String,default:void 0},readOnly:{type:[Boolean,Object],default:void 0},i18n:{type:Object,default:void 0},link:{type:Object,default:void 0},linkPaste:{type:Object,default:void 0},inlineToolbar:{type:[Array,Boolean],default:void 0},tunes:{type:Array,default:void 0},style:{type:Object,default:void 0},theme:{type:String,default:void 0},scrollToBlock:{type:Object,default:void 0},user:{type:Object,default:void 0},resolveUser:{type:Function,default:void 0},notifierPosition:{type:String,default:void 0},notifier:{type:Function,default:void 0},width:{type:String,default:void 0},onBeforeRender:{type:Function,default:void 0},onBeforePaste:{type:Function,default:void 0},onEnter:{type:Function,default:void 0},recreateKey:{type:null}},emits:{ready:e=>!0,change:e=>!0,save:e=>!0,"update:data":e=>!0,"after-render":e=>!0,"theme-change":e=>!0,"blocks-rendered":e=>!0,"block-rendered":e=>!0},setup(t,{emit:n,expose:r,attrs:i}){let a=(0,e.getCurrentInstance)(),o=e=>{let t=a==null?void 0:a.vnode.props;return t!=null&&e in t},s=()=>{let e={};for(let n of j){let r=t[n];r!==void 0&&(e[n]=r)}return o(`onChange`)&&(e.onChange=(e,t)=>{n(`change`,{api:e,event:t})}),(o(`onSave`)||o(`onUpdate:data`))&&(e.onSave=e=>{n(`update:data`,e),n(`save`,e)}),o(`onAfterRender`)&&(e.onAfterRender=e=>{n(`after-render`,e)}),o(`onThemeChange`)&&(e.onThemeChange=e=>{n(`theme-change`,e)}),e},c=w(()=>s(),()=>t.recreateKey);(0,e.watch)(c,(e,t,r)=>{if(e===null)return;let i=[];if(o(`onBlocksRendered`)){let t=e=>n(`blocks-rendered`,e);e.on(`blocks:rendered`,t),i.push([`blocks:rendered`,t])}if(o(`onBlockRendered`)){let t=e=>n(`block-rendered`,e);e.on(`block:rendered`,t),i.push([`block:rendered`,t])}r(()=>{for(let[t,n]of i)e.off(t,n)})});let l={last:null};return(0,e.watch)(c,e=>{e!==null&&e!==l.last&&(l.last=e,n(`ready`,e))}),r({instance:(0,e.computed)(()=>c.value),save:()=>{var e;return(e=c.value)==null?void 0:e.save()},focus:e=>{var t;(t=c.value)==null||t.focus(e)},render:e=>{var t;return(t=c.value)==null?void 0:t.render(e)}}),()=>(0,e.h)(A,f({editor:c.value},i))}});function N(t){var r;let i=(0,e.defineComponent)({name:`VueBlock(${t.type})`,props:{ctx:{type:Object,required:!0}},setup(e){return t.setup(e.ctx)}});return r=class{static get toolbox(){return t.toolbox}static get isReadOnlySupported(){return!0}constructor(r){var i,a;this.hostEl=null,this.pendingDispatch=!1,this.commit=e=>{let r=(0,n.fillDefaults)(t.propSchema,f(f({},this.mirror),e));(0,n.deepEqual)(r,this.mirror)||(this.mirror=r,this.lastRendered=r,this.dataRef.value=r,this.flushDispatch())},this.blockApi=r.block;let o=(i=r.config)==null?{}:i;this.registry=o[_];let s=r.api;this.pointerDrag=()=>{var e;return(s==null||(e=s.blocks)==null?void 0:e.isPointerDragActive)===!0},this.mirror=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)((a=r.data)==null?{}:a)),this.lastRendered=this.mirror,this.dataRef=(0,e.shallowRef)(this.mirror),this.readOnlyRef=(0,e.shallowRef)(r.readOnly);let c=this.blockApi;this.childrenComponent=(0,e.defineComponent)({name:`VueBlockChildren(${t.type})`,setup(){let t=(0,e.ref)(null),r=()=>{t.value!==null&&(0,n.mountChildBlocks)(t.value,c.getChildren())};return(0,e.onMounted)(r),(0,e.onUpdated)(r),()=>(0,e.h)(`div`,{ref:t,[n.DATA_ATTR.nestedBlocks]:``})}})}render(){var e;let t=document.createElement(`div`);t.setAttribute(`data-blok-mutation-free`,`true`),this.hostEl=t;let n={data:this.dataRef,commit:this.commit,block:this.blockApi,readOnly:this.readOnlyRef,BlockChildren:this.childrenComponent};return(e=this.registry)==null||e.register(this.blockApi.id,{hostEl:t,component:i,props:{ctx:n}}),t}rendered(){var e;(e=t.onRendered)==null||e.call(t,this.blockApi)}save(){return this.mirror}async setData(r){var i=this;let a=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)(r==null?{}:r));return(0,n.deepEqual)(a,i.lastRendered)?!0:(i.mirror=a,i.lastRendered=a,i.dataRef.value=a,await(0,e.nextTick)(),!0)}setReadOnly(e){this.readOnlyRef.value=e}moved(){var e;(e=t.onMoved)==null||e.call(t,this.blockApi)}removed(){var e,n;(e=this.registry)==null||e.unregister(this.blockApi.id),(n=t.onRemoved)==null||n.call(t,this.blockApi)}destroy(){var e;(e=this.registry)==null||e.unregister(this.blockApi.id)}flushDispatch(){if(!this.pointerDrag()){this.pendingDispatch=!1,this.blockApi.dispatchChange();return}if(this.pendingDispatch)return;this.pendingDispatch=!0;let e=()=>{if(this.pointerDrag()){requestAnimationFrame(e);return}this.pendingDispatch=!1,this.blockApi.dispatchChange()};requestAnimationFrame(e)}},r.__isBlokVueBlock=!0,r}exports.BLOK_DEFAULT_CONFIG=p,exports.BlokContent=A,exports.BlokEditor=M,exports.createVueBlock=N,exports.provideBlok=m,exports.useBlocks=E,exports.useBlok=w,exports.useBlokDefaults=h,exports.useBlokReady=D;
package/dist/index.mjs CHANGED
@@ -9,41 +9,41 @@ function A(e, t) {
9
9
  function j(e) {
10
10
  return k.get(e);
11
11
  }
12
- function ee(e) {
12
+ function M(e) {
13
13
  k.delete(e);
14
14
  }
15
15
  //#endregion
16
- //#region \0@oxc-project+runtime@0.126.0/helpers/typeof.js
17
- function M(e) {
16
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/typeof.js
17
+ function N(e) {
18
18
  "@babel/helpers - typeof";
19
- return M = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
19
+ return N = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
20
20
  return typeof e;
21
21
  } : function(e) {
22
22
  return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
23
- }, M(e);
23
+ }, N(e);
24
24
  }
25
25
  //#endregion
26
- //#region \0@oxc-project+runtime@0.126.0/helpers/toPrimitive.js
27
- function N(e, t) {
28
- if (M(e) != "object" || !e) return e;
26
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPrimitive.js
27
+ function P(e, t) {
28
+ if (N(e) != "object" || !e) return e;
29
29
  var n = e[Symbol.toPrimitive];
30
30
  if (n !== void 0) {
31
31
  var r = n.call(e, t || "default");
32
- if (M(r) != "object") return r;
32
+ if (N(r) != "object") return r;
33
33
  throw TypeError("@@toPrimitive must return a primitive value.");
34
34
  }
35
35
  return (t === "string" ? String : Number)(e);
36
36
  }
37
37
  //#endregion
38
- //#region \0@oxc-project+runtime@0.126.0/helpers/toPropertyKey.js
39
- function P(e) {
40
- var t = N(e, "string");
41
- return M(t) == "symbol" ? t : t + "";
38
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPropertyKey.js
39
+ function F(e) {
40
+ var t = P(e, "string");
41
+ return N(t) == "symbol" ? t : t + "";
42
42
  }
43
43
  //#endregion
44
- //#region \0@oxc-project+runtime@0.126.0/helpers/defineProperty.js
45
- function F(e, t, n) {
46
- return (t = P(t)) in e ? Object.defineProperty(e, t, {
44
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/defineProperty.js
45
+ function I(e, t, n) {
46
+ return (t = F(t)) in e ? Object.defineProperty(e, t, {
47
47
  value: n,
48
48
  enumerable: !0,
49
49
  configurable: !0,
@@ -51,8 +51,8 @@ function F(e, t, n) {
51
51
  }) : e[t] = n, e;
52
52
  }
53
53
  //#endregion
54
- //#region \0@oxc-project+runtime@0.126.0/helpers/objectSpread2.js
55
- function I(e, t) {
54
+ //#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectSpread2.js
55
+ function L(e, t) {
56
56
  var n = Object.keys(e);
57
57
  if (Object.getOwnPropertySymbols) {
58
58
  var r = Object.getOwnPropertySymbols(e);
@@ -62,12 +62,12 @@ function I(e, t) {
62
62
  }
63
63
  return n;
64
64
  }
65
- function L(e) {
65
+ function R(e) {
66
66
  for (var t = 1; t < arguments.length; t++) {
67
67
  var n = arguments[t] == null ? {} : arguments[t];
68
- t % 2 ? I(Object(n), !0).forEach(function(t) {
69
- F(e, t, n[t]);
70
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : I(Object(n)).forEach(function(t) {
68
+ t % 2 ? L(Object(n), !0).forEach(function(t) {
69
+ I(e, t, n[t]);
70
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : L(Object(n)).forEach(function(t) {
71
71
  Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
72
72
  });
73
73
  }
@@ -75,25 +75,25 @@ function L(e) {
75
75
  }
76
76
  //#endregion
77
77
  //#region src/provide-blok.ts
78
- var R = Symbol("BLOK_DEFAULT_CONFIG");
79
- function z(e) {
80
- m(R, e);
78
+ var z = Symbol("BLOK_DEFAULT_CONFIG");
79
+ function B(e) {
80
+ m(z, e);
81
81
  }
82
- function B() {
83
- return o(R, {});
82
+ function V() {
83
+ return o(z, {});
84
84
  }
85
- function V(e, t) {
85
+ function H(e, t) {
86
86
  if (Object.keys(e).length === 0) return t;
87
- let n = L({}, e);
87
+ let n = R({}, e);
88
88
  for (let e of Object.keys(t)) {
89
89
  let r = t[e];
90
90
  r !== void 0 && (n[e] = r);
91
91
  }
92
- return (e.tools !== void 0 || t.tools !== void 0) && (n.tools = L(L({}, e.tools), t.tools)), n;
92
+ return (e.tools !== void 0 || t.tools !== void 0) && (n.tools = R(R({}, e.tools), t.tools)), n;
93
93
  }
94
94
  //#endregion
95
95
  //#region src/block-portal-registry.ts
96
- var H = "__blokPortalRegistry", U = () => {
96
+ var U = "__blokPortalRegistry", W = () => {
97
97
  let e = h(/* @__PURE__ */ new Map());
98
98
  return {
99
99
  entries: e,
@@ -108,19 +108,19 @@ var H = "__blokPortalRegistry", U = () => {
108
108
  r !== void 0 && Object.assign(r.props, n);
109
109
  }
110
110
  };
111
- }, W = /* @__PURE__ */ new WeakMap();
112
- function G(e, t) {
113
- W.set(e, t);
114
- }
115
- function K(e) {
116
- return W.get(e);
111
+ }, G = /* @__PURE__ */ new WeakMap();
112
+ function K(e, t) {
113
+ G.set(e, t);
117
114
  }
118
115
  function q(e) {
119
- W.delete(e);
116
+ return G.get(e);
117
+ }
118
+ function J(e) {
119
+ G.delete(e);
120
120
  }
121
121
  //#endregion
122
122
  //#region src/useBlok.ts
123
- var J = (e, t) => {
123
+ var Y = (e, t) => {
124
124
  if (typeof e != "object" || !e) return e;
125
125
  let n = {};
126
126
  for (let [i, a] of Object.entries(e)) {
@@ -130,24 +130,24 @@ var J = (e, t) => {
130
130
  n[i] = a;
131
131
  continue;
132
132
  }
133
- let o = typeof a == "function" ? { class: a } : L({}, a);
134
- o.config = L(L({}, (r = o.config) == null ? {} : r), {}, { [H]: t }), n[i] = o;
133
+ let o = typeof a == "function" ? { class: a } : R({}, a);
134
+ o.config = R(R({}, (r = o.config) == null ? {} : r), {}, { [U]: t }), n[i] = o;
135
135
  }
136
136
  return n;
137
137
  };
138
- function Y(e, t) {
139
- let n = _(null), r = o(R, {}), i = () => V(r, y(e)), a = {
138
+ function X(e, t) {
139
+ let n = _(null), r = o(z, {}), i = () => H(r, y(e)), a = {
140
140
  current: null,
141
141
  holder: null,
142
142
  lastRenderedData: i().data,
143
143
  seededEditor: null,
144
144
  renderChain: Promise.resolve()
145
145
  }, s = () => {
146
- let t = L({}, V(v(r), v(y(e))));
146
+ let t = R({}, H(v(r), v(y(e))));
147
147
  return delete t.holder, t.data !== void 0 && (t.data = v(t.data)), t;
148
148
  }, c = () => {
149
149
  if (a.current !== null) {
150
- ee(a.current), q(a.current);
150
+ M(a.current), J(a.current);
151
151
  try {
152
152
  a.current.destroy();
153
153
  } catch (e) {}
@@ -156,27 +156,66 @@ function Y(e, t) {
156
156
  }, u = () => {
157
157
  let e = document.createElement("div");
158
158
  a.holder = e;
159
- let t = s(), r = U();
160
- t.tools !== void 0 && (t.tools = J(t.tools, r)), typeof t.onSave == "function" && (t.onSave = (...e) => {
159
+ let t = s(), r = W();
160
+ t.tools !== void 0 && (t.tools = Y(t.tools, r)), typeof t.onSave == "function" && (t.onSave = (...e) => {
161
161
  var t, n;
162
162
  a.lastRenderedData = e[0], (t = (n = i()).onSave) == null || t.call(n, ...e);
163
163
  });
164
- let o = new x(L(L({}, t), {}, { holder: e }));
165
- a.current = o, A(o, e), G(o, r), o.isReady.then(() => {
164
+ let o = new x(R(R({}, t), {}, { holder: e }));
165
+ a.current = o, A(o, e), K(o, r), o.isReady.then(() => {
166
166
  a.current === o && (n.value = o);
167
167
  }).catch(() => {
168
168
  a.current === o && c();
169
169
  });
170
170
  };
171
- return b([n, () => O(i().readOnly).enabled], ([e, t]) => {
172
- e && e.readOnly.set(t);
171
+ b([
172
+ n,
173
+ () => O(i().readOnly).enabled,
174
+ () => O(i().readOnly).hideControls,
175
+ () => typeof i().readOnly == "object"
176
+ ], ([e, t, n, r]) => {
177
+ e && (r ? e.readOnly.set(t, { hideControls: n }) : e.readOnly.set(t));
178
+ }, { immediate: !0 }), b([n, () => i().hideToolbar], ([e, t]) => {
179
+ e && e.toolbar.setHidden(!!t);
173
180
  }, { immediate: !0 }), b([n, () => i().theme], ([e, t]) => {
174
181
  e && t !== void 0 && e.theme.set(t);
175
182
  }, { immediate: !0 }), b([n, () => i().width], ([e, t]) => {
176
183
  e && t !== void 0 && e.width.set(t);
177
184
  }, { immediate: !0 }), b([n, () => i().placeholder], ([e, t]) => {
178
185
  e && t !== void 0 && e.placeholder.set(t);
179
- }, { immediate: !0 }), b([n, () => i().autofocus], ([e, t]) => {
186
+ }, { immediate: !0 });
187
+ let f = { value: void 0 };
188
+ b([n, () => {
189
+ var e;
190
+ return (e = i().style) == null ? void 0 : e.tokens;
191
+ }], ([e, t]) => {
192
+ !e || t === void 0 || T(t, f.value) || (f.value = R({}, t), e.tokens.set(t));
193
+ }, {
194
+ immediate: !0,
195
+ deep: !0
196
+ });
197
+ let p = { value: i().i18n };
198
+ b([n, () => i().i18n], ([e, t]) => {
199
+ if (!e || t === void 0 || T(t, p.value)) return;
200
+ p.value = R({}, t);
201
+ let { locale: n, messages: r, direction: i } = t;
202
+ e.i18n.update(R(R(R({}, n === void 0 ? {} : { locale: n }), r === void 0 ? {} : { messages: r }), i === void 0 ? {} : { direction: i }));
203
+ }, {
204
+ immediate: !0,
205
+ deep: !0
206
+ });
207
+ let m = {
208
+ editor: null,
209
+ value: void 0
210
+ };
211
+ return b([n, () => i().inlineToolbar], ([e, t]) => {
212
+ if (!e || t === void 0 || m.editor === e && T(t, m.value)) return;
213
+ let n = Array.isArray(t) ? [...t] : t;
214
+ m.editor = e, m.value = n, e.tools.setInlineToolbar(n);
215
+ }, {
216
+ immediate: !0,
217
+ deep: !0
218
+ }), b([n, () => i().autofocus], ([e, t]) => {
180
219
  e && t && e.focus();
181
220
  }, { immediate: !0 }), b([n, () => i().data], ([e, t]) => {
182
221
  if (!(!e || t === void 0)) {
@@ -192,8 +231,8 @@ function Y(e, t) {
192
231
  }
193
232
  //#endregion
194
233
  //#region src/useBlocks.ts
195
- var X = "block changed";
196
- function Z(e) {
234
+ var Z = "block changed";
235
+ function Q(e) {
197
236
  let t = _(0), n = () => {
198
237
  let t = y(e);
199
238
  return t === null ? null : v(t);
@@ -203,7 +242,7 @@ function Z(e) {
203
242
  editor: null,
204
243
  handler: null
205
244
  }, o = () => {
206
- a.editor !== null && a.handler !== null && a.editor.off(X, a.handler), a.editor = null, a.handler = null;
245
+ a.editor !== null && a.handler !== null && a.editor.off(Z, a.handler), a.editor = null, a.handler = null;
207
246
  };
208
247
  return b(() => n(), (e) => {
209
248
  if (o(), t.value += 1, e === null) {
@@ -213,7 +252,7 @@ function Z(e) {
213
252
  let n = () => {
214
253
  t.value += 1;
215
254
  };
216
- e.on(X, n), a.editor = e, a.handler = n, i.value = w(e, r);
255
+ e.on(Z, n), a.editor = e, a.handler = n, i.value = w(e, r);
217
256
  }, { immediate: !0 }), f(o), {
218
257
  getById: (e) => i.value.getById(e),
219
258
  getChildren: (e) => i.value.getChildren(e),
@@ -247,8 +286,21 @@ function Z(e) {
247
286
  };
248
287
  }
249
288
  //#endregion
289
+ //#region src/useBlokReady.ts
290
+ function ee(e = {}) {
291
+ let { within: t, settleOn: n } = e, r = _(!1), i = () => {
292
+ var e;
293
+ let i = t === void 0 || (e = y(t)) == null ? null : e;
294
+ r.value = t !== void 0 && i === null ? !1 : x.readyState({
295
+ within: i,
296
+ settleOn: n
297
+ }).ready;
298
+ };
299
+ return f(x.subscribeReady(i)), d(i), r;
300
+ }
301
+ //#endregion
250
302
  //#region src/BlockPortalHost.ts
251
- var Q = r({
303
+ var te = r({
252
304
  name: "BlockErrorBoundary",
253
305
  setup(e, { slots: t }) {
254
306
  return u(() => !1), () => {
@@ -256,7 +308,7 @@ var Q = r({
256
308
  return (e = t.default) == null ? void 0 : e.call(t);
257
309
  };
258
310
  }
259
- }), te = r({
311
+ }), ne = r({
260
312
  name: "BlockPortalHost",
261
313
  props: { registry: {
262
314
  type: Object,
@@ -266,7 +318,7 @@ var Q = r({
266
318
  return () => a(e, Array.from(n.registry.entries.entries()).map(([e, n]) => a(t, {
267
319
  key: e,
268
320
  to: n.hostEl
269
- }, [a(Q, null, { default: () => a(n.component, n.props) })])));
321
+ }, [a(te, null, { default: () => a(n.component, n.props) })])));
270
322
  }
271
323
  }), $ = r({
272
324
  name: "BlokContent",
@@ -290,11 +342,11 @@ var Q = r({
290
342
  }), l(() => {
291
343
  r(e.editor);
292
344
  }), () => {
293
- let n = e.editor, r = n === null ? void 0 : K(v(n));
294
- return a("div", { ref: t }, r === void 0 ? [] : [a(te, { registry: r })]);
345
+ let n = e.editor, r = n === null ? void 0 : q(v(n));
346
+ return a("div", { ref: t }, r === void 0 ? [] : [a(ne, { registry: r })]);
295
347
  };
296
348
  }
297
- }), ne = /* @__PURE__ */ "autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter".split("."), re = r({
349
+ }), re = /* @__PURE__ */ "autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter".split("."), ie = r({
298
350
  name: "BlokEditor",
299
351
  inheritAttrs: !1,
300
352
  props: {
@@ -355,7 +407,7 @@ var Q = r({
355
407
  default: void 0
356
408
  },
357
409
  readOnly: {
358
- type: Boolean,
410
+ type: [Boolean, Object],
359
411
  default: void 0
360
412
  },
361
413
  i18n: {
@@ -440,7 +492,7 @@ var Q = r({
440
492
  return t != null && e in t;
441
493
  }, l = () => {
442
494
  let n = {};
443
- for (let t of ne) {
495
+ for (let t of re) {
444
496
  let r = e[t];
445
497
  r !== void 0 && (n[t] = r);
446
498
  }
@@ -456,7 +508,7 @@ var Q = r({
456
508
  }), c("onThemeChange") && (n.onThemeChange = (e) => {
457
509
  t("theme-change", e);
458
510
  }), n;
459
- }, u = Y(() => l(), () => e.recreateKey);
511
+ }, u = X(() => l(), () => e.recreateKey);
460
512
  b(u, (e, n, r) => {
461
513
  if (e === null) return;
462
514
  let i = [];
@@ -489,12 +541,12 @@ var Q = r({
489
541
  var t;
490
542
  return (t = u.value) == null ? void 0 : t.render(e);
491
543
  }
492
- }), () => a($, L({ editor: u.value }, o));
544
+ }), () => a($, R({ editor: u.value }, o));
493
545
  }
494
546
  });
495
547
  //#endregion
496
548
  //#region src/createVueBlock.ts
497
- function ie(e) {
549
+ function ae(e) {
498
550
  var t;
499
551
  let n = r({
500
552
  name: `VueBlock(${e.type})`,
@@ -516,11 +568,11 @@ function ie(e) {
516
568
  constructor(t) {
517
569
  var n, i;
518
570
  this.hostEl = null, this.pendingDispatch = !1, this.commit = (t) => {
519
- let n = E(e.propSchema, L(L({}, this.mirror), t));
571
+ let n = E(e.propSchema, R(R({}, this.mirror), t));
520
572
  T(n, this.mirror) || (this.mirror = n, this.lastRendered = n, this.dataRef.value = n, this.flushDispatch());
521
573
  }, this.blockApi = t.block;
522
574
  let o = (n = t.config) == null ? {} : n;
523
- this.registry = o[H];
575
+ this.registry = o[U];
524
576
  let s = t.api;
525
577
  this.pointerDrag = () => {
526
578
  var e;
@@ -603,4 +655,4 @@ function ie(e) {
603
655
  }, t.__isBlokVueBlock = !0, t;
604
656
  }
605
657
  //#endregion
606
- export { R as BLOK_DEFAULT_CONFIG, $ as BlokContent, re as BlokEditor, ie as createVueBlock, z as provideBlok, Z as useBlocks, Y as useBlok, B as useBlokDefaults };
658
+ export { z as BLOK_DEFAULT_CONFIG, $ as BlokContent, ie as BlokEditor, ae as createVueBlock, B as provideBlok, Q as useBlocks, X as useBlok, V as useBlokDefaults, ee as useBlokReady };
package/package.json CHANGED
@@ -1,14 +1,35 @@
1
1
  {
2
2
  "name": "@bloklabs/vue",
3
- "version": "1.2.6",
4
- "description": "Vue 3 bindings for the Blok editor",
3
+ "version": "1.4.0",
4
+ "description": "Vue block editor — official Vue 3 bindings for Blok, the headless Notion-like rich text editor. Composables and components that render blocks and save to JSON.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "JackUait",
7
+ "homepage": "https://blokeditor.com",
7
8
  "repository": {
8
9
  "type": "git",
9
10
  "url": "git+https://github.com/JackUait/blok.git",
10
11
  "directory": "packages/vue"
11
12
  },
13
+ "bugs": {
14
+ "url": "https://github.com/JackUait/blok/issues"
15
+ },
16
+ "keywords": [
17
+ "blok",
18
+ "vue",
19
+ "vue3",
20
+ "vue-component",
21
+ "block-editor",
22
+ "rich-text-editor",
23
+ "wysiwyg",
24
+ "editor",
25
+ "notion",
26
+ "notion-like",
27
+ "headless",
28
+ "block-based",
29
+ "contenteditable",
30
+ "json",
31
+ "typescript"
32
+ ],
12
33
  "type": "module",
13
34
  "sideEffects": false,
14
35
  "main": "./dist/index.cjs",
@@ -33,7 +54,7 @@
33
54
  "build": "yarn run -T vite build --mode production"
34
55
  },
35
56
  "peerDependencies": {
36
- "@bloklabs/core": "^1.2.6",
57
+ "@bloklabs/core": "^1.4.0",
37
58
  "vue": "^3.5.0"
38
59
  }
39
60
  }
package/src/BlokEditor.ts CHANGED
@@ -45,7 +45,9 @@ export const BlokEditor = defineComponent({
45
45
  data: { type: Object as PropType<OutputData>, default: undefined },
46
46
  minHeight: { type: Number, default: undefined },
47
47
  logLevel: { type: String as PropType<BlokConfig['logLevel']>, default: undefined },
48
- readOnly: { type: Boolean as PropType<boolean | undefined>, default: undefined },
48
+ // [Boolean, Object]: the object form ({ hideControls }) must not be dropped
49
+ // or dev-warned — it always means read-only enabled (reactive contract).
50
+ readOnly: { type: [Boolean, Object] as PropType<BlokConfig['readOnly']>, default: undefined },
49
51
  i18n: { type: Object as PropType<BlokConfig['i18n']>, default: undefined },
50
52
  link: { type: Object as PropType<BlokConfig['link']>, default: undefined },
51
53
  linkPaste: { type: Object as PropType<BlokConfig['linkPaste']>, default: undefined },
@@ -131,7 +133,7 @@ export const BlokEditor = defineComponent({
131
133
  };
132
134
  }
133
135
 
134
- return config as UseBlokConfig;
136
+ return config;
135
137
  };
136
138
 
137
139
  const editor = useBlok(
@@ -52,7 +52,7 @@ export const createBlockPortalRegistry = (): BlockPortalRegistry => {
52
52
  const entries = reactive(new Map<string, BlockPortalEntry>());
53
53
 
54
54
  return {
55
- entries: entries as ReadonlyMap<string, BlockPortalEntry>,
55
+ entries: entries,
56
56
  register(id: string, entry: BlockPortalEntry): void {
57
57
  // markRaw so the reactive Map (which must still track add/delete) does NOT
58
58
  // deep-proxy the entry — a proxied component DEFINITION or DOM host would
@@ -218,7 +218,7 @@ export function createVueBlock<Data = BlockToolData>(
218
218
 
219
219
  public save(): BlockToolData {
220
220
  // The complete, frozen, toRaw-clean mirror — never the DOM, never partial.
221
- return this.mirror as BlockToolData;
221
+ return this.mirror;
222
222
  }
223
223
 
224
224
  public async setData(newData: BlockToolData): Promise<boolean> {
package/src/index.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export { useBlok } from './useBlok';
2
2
  export { useBlocks } from './useBlocks';
3
+ export { useBlokReady } from './useBlokReady';
3
4
  export { BlokContent } from './BlokContent';
4
5
  export { BlokEditor } from './BlokEditor';
5
6
  export { provideBlok, useBlokDefaults, BLOK_DEFAULT_CONFIG } from './provide-blok';
6
7
  export { createVueBlock } from './createVueBlock';
7
8
  export type { UseBlokConfig, BlokContentProps } from './types';
9
+ export type { UseBlokReadyOptions } from './useBlokReady';
8
10
  export type {
9
11
  UseBlocksApi,
10
12
  BlockNode,
@@ -61,5 +61,5 @@ export function mergeBlokDefaults(
61
61
  merged.tools = { ...defaults.tools, ...config.tools };
62
62
  }
63
63
 
64
- return merged as UseBlokConfig;
64
+ return merged;
65
65
  }
package/src/types.ts CHANGED
@@ -6,7 +6,12 @@ import type { BlokConfig, Blok, EditorWidth } from '@/types';
6
6
  * reactive `width` prop.
7
7
  *
8
8
  * Reactive props (sync after mount without recreation):
9
- * - `readOnly` — calls `editor.readOnly.set(value)`
9
+ * - `readOnly` — calls `editor.readOnly.set(enabled, { hideControls })`; the
10
+ * object form's `hideControls` is live too (toggles in place — see
11
+ * `editor.readOnly.togglesInPlace`)
12
+ * - `hideToolbar` — calls `editor.toolbar.setHidden(value)` (undefined → false)
13
+ * - `inlineToolbar` — calls `editor.tools.setInlineToolbar(value)`
14
+ * (content-compared, so a fresh array with the same names is a no-op)
10
15
  * - `autofocus` — calls `editor.focus()` when changed to true
11
16
  * - `theme` — calls `editor.theme.set(value)`
12
17
  * - `width` — calls `editor.width.set(value)`
package/src/useBlok.ts CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  type BlockPortalRegistry,
20
20
  } from './block-portal-registry';
21
21
  import { setRegistry, removeRegistry } from './registry-map';
22
- import type { Blok, LooseOutputData, OutputData } from '@/types';
22
+ import type { Blok, BlokConfig, LooseOutputData, OutputData } from '@/types';
23
23
  import type { UseBlokConfig } from './types';
24
24
 
25
25
  /**
@@ -51,7 +51,7 @@ const injectPortalRegistry = (tools: unknown, registry: BlockPortalRegistry): un
51
51
  typeof entry === 'function' ? { class: entry } : { ...(entry as Record<string, unknown>) };
52
52
 
53
53
  base.config = {
54
- ...((base.config as Record<string, unknown> | undefined) ?? {}),
54
+ ...((base.config) ?? {}),
55
55
  [BLOK_PORTAL_REGISTRY_CONFIG_KEY]: registry,
56
56
  };
57
57
  result[name] = base;
@@ -176,7 +176,7 @@ export function useBlok(
176
176
  };
177
177
  }
178
178
 
179
- const blok = new BlokRuntime({ ...snapshot, holder }) as unknown as Blok;
179
+ const blok = new BlokRuntime({ ...snapshot, holder });
180
180
 
181
181
  state.current = blok;
182
182
  setHolder(blok, holder);
@@ -199,11 +199,31 @@ export function useBlok(
199
199
  // once the instance appears (the Vue analog of React's `editor` effect-dep).
200
200
  // `theme`/`width`/`placeholder` guard on `=== undefined` (NOT falsiness) so a
201
201
  // real `placeholder: false` (clear) still propagates.
202
+ // readOnly syncs the full normalized pair: `enabled` always, `hideControls`
203
+ // only for the object form (`readOnly.set` toggles IN PLACE — see
204
+ // `readOnly.togglesInPlace` — so no recreation is ever needed).
202
205
  watch(
203
- [editor, () => normalizeReadOnlyConfig(mergedConfig().readOnly).enabled],
204
- ([ed, readOnlyEnabled]) => {
206
+ [
207
+ editor,
208
+ () => normalizeReadOnlyConfig(mergedConfig().readOnly).enabled,
209
+ () => normalizeReadOnlyConfig(mergedConfig().readOnly).hideControls,
210
+ () => typeof mergedConfig().readOnly === 'object',
211
+ ],
212
+ ([ed, readOnlyEnabled, hideControls, isObjectForm]) => {
205
213
  if (ed) {
206
- void ed.readOnly.set(readOnlyEnabled);
214
+ void (isObjectForm ? ed.readOnly.set(readOnlyEnabled, { hideControls }) : ed.readOnly.set(readOnlyEnabled));
215
+ }
216
+ },
217
+ { immediate: true }
218
+ );
219
+
220
+ // hideToolbar toggles the hover toolbar and its gutter in place. Coerces
221
+ // undefined to false (like readOnly) so clearing the option propagates.
222
+ watch(
223
+ [editor, () => mergedConfig().hideToolbar],
224
+ ([ed, hideToolbar]) => {
225
+ if (ed) {
226
+ ed.toolbar.setHidden(Boolean(hideToolbar));
207
227
  }
208
228
  },
209
229
  { immediate: true }
@@ -239,6 +259,88 @@ export function useBlok(
239
259
  { immediate: true }
240
260
  );
241
261
 
262
+ // Theme tokens were construction-only, so a host with a live light/dark
263
+ // toggle had to recreate the editor or hand-write the global stylesheet Blok
264
+ // already injects. Deep-equal-deduped because `tokens` is typically a fresh
265
+ // object literal; `deep: true` so mutating the same object still propagates.
266
+ const appliedTokens: { value: Record<string, string> | undefined } = { value: undefined };
267
+
268
+ watch(
269
+ [editor, () => mergedConfig().style?.tokens],
270
+ ([ed, tokens]) => {
271
+ if (!ed || tokens === undefined || deepEqual(tokens, appliedTokens.value)) {
272
+ return;
273
+ }
274
+
275
+ appliedTokens.value = { ...tokens };
276
+ ed.tokens.set(tokens);
277
+ },
278
+ { immediate: true, deep: true }
279
+ );
280
+
281
+ // `config.i18n` was consumed once during boot, so a host driving a language
282
+ // switcher had to recreate the editor (losing caret, focus and undo stack)
283
+ // to relabel the UI. This drives the runtime `i18n.update` API instead.
284
+ // Deep-equal-deduped and `deep: true` for the same reasons as tokens.
285
+ // `defaultLocale` is not forwarded: it only affects the INITIAL locale
286
+ // resolution, so it is inert after mount.
287
+ /*
288
+ * Seeded with the mount-time value: construction already applied it, so the
289
+ * immediate run is a no-op and only genuine changes push.
290
+ */
291
+ const appliedI18n: { value: BlokConfig['i18n'] | undefined } = { value: mergedConfig().i18n };
292
+
293
+ watch(
294
+ [editor, () => mergedConfig().i18n],
295
+ ([ed, i18n]) => {
296
+ if (!ed || i18n === undefined || deepEqual(i18n, appliedI18n.value)) {
297
+ return;
298
+ }
299
+
300
+ appliedI18n.value = { ...i18n };
301
+
302
+ const { locale, messages, direction } = i18n;
303
+
304
+ void ed.i18n.update({
305
+ ...(locale === undefined ? {} : { locale }),
306
+ ...(messages === undefined ? {} : { messages }),
307
+ ...(direction === undefined ? {} : { direction }),
308
+ });
309
+ },
310
+ { immediate: true, deep: true }
311
+ );
312
+
313
+ // inlineToolbar re-assigns inline tools in place. Content-compared (not
314
+ // identity-compared) because `boolean | string[]` configs are typically fresh
315
+ // array literals; the baseline is tracked per editor instance so a recreated
316
+ // editor gets the current value applied again. `deep: true` so mutating the
317
+ // same array still propagates (mirrors the tokens watch).
318
+ const appliedInlineToolbar: { editor: Blok | null; value: boolean | string[] | undefined } = {
319
+ editor: null,
320
+ value: undefined,
321
+ };
322
+
323
+ watch(
324
+ [editor, () => mergedConfig().inlineToolbar],
325
+ ([ed, inlineToolbar]) => {
326
+ if (!ed || inlineToolbar === undefined) {
327
+ return;
328
+ }
329
+
330
+ if (appliedInlineToolbar.editor === ed && deepEqual(inlineToolbar, appliedInlineToolbar.value)) {
331
+ return;
332
+ }
333
+
334
+ // De-proxy: copy an array so no Vue reactive proxy reaches core.
335
+ const plain = Array.isArray(inlineToolbar) ? [...inlineToolbar] : inlineToolbar;
336
+
337
+ appliedInlineToolbar.editor = ed;
338
+ appliedInlineToolbar.value = plain;
339
+ ed.tools.setInlineToolbar(plain);
340
+ },
341
+ { immediate: true, deep: true }
342
+ );
343
+
242
344
  watch(
243
345
  [editor, () => mergedConfig().autofocus],
244
346
  ([ed, autofocus]) => {
@@ -0,0 +1,70 @@
1
+ // packages/vue/src/useBlokReady.ts
2
+ import {
3
+ onMounted,
4
+ onScopeDispose,
5
+ shallowRef,
6
+ toValue,
7
+ type MaybeRefOrGetter,
8
+ type ShallowRef,
9
+ } from 'vue';
10
+
11
+ import { Blok as BlokRuntime } from '@bloklabs/core';
12
+
13
+ /** Options accepted by {@link useBlokReady}. */
14
+ export interface UseBlokReadyOptions {
15
+ /**
16
+ * Restrict the wait to editors mounted inside this element. Accepts the
17
+ * template ref you already hold on the container (or a getter); it is
18
+ * re-read on every readiness change, so a ref that fills in on mount is
19
+ * picked up.
20
+ *
21
+ * Omit it to observe every editor on the page. Passing it while it still
22
+ * resolves to null reports NOT ready — an unresolved scope must never fall
23
+ * back to the page-global one.
24
+ */
25
+ within?: MaybeRefOrGetter<Element | null | undefined>;
26
+ /**
27
+ * `'ready'` (default) settles when each editor has finished booting.
28
+ * `'rendered'` also waits for its content to be in the DOM and re-arms on
29
+ * every post-boot re-render.
30
+ */
31
+ settleOn?: 'ready' | 'rendered';
32
+ }
33
+
34
+ /**
35
+ * Vue composable exposing the live readiness of the Blok editors in a DOM
36
+ * scope as a boolean ref.
37
+ *
38
+ * The readiness logic itself is framework-agnostic and lives in core
39
+ * (`Blok.readyState` / `Blok.subscribeReady`) — the SAME implementation behind
40
+ * React's `useBlokReady` and Angular's `injectBlokReady`, so the three adapters
41
+ * cannot drift. This composable supplies only Vue's reactivity wrapper: a
42
+ * `shallowRef` re-read on every registry change, with the subscription
43
+ * disposed by the surrounding effect scope.
44
+ *
45
+ * The ref starts `false` and takes its first real reading on mount, once the
46
+ * template ref has filled in. Over-waiting is safe; under-waiting is a bug.
47
+ * @param options - scope and readiness depth
48
+ */
49
+ export function useBlokReady(options: UseBlokReadyOptions = {}): Readonly<ShallowRef<boolean>> {
50
+ const { within, settleOn } = options;
51
+ const ready = shallowRef(false);
52
+
53
+ const read = (): void => {
54
+ const scope = within === undefined ? null : (toValue(within) ?? null);
55
+
56
+ // A scope that was asked for but has not resolved yet is NOT the global
57
+ // scope — reporting ready here would gate on the wrong set of editors.
58
+ ready.value = within !== undefined && scope === null
59
+ ? false
60
+ : BlokRuntime.readyState({
61
+ within: scope,
62
+ settleOn,
63
+ }).ready;
64
+ };
65
+
66
+ onScopeDispose(BlokRuntime.subscribeReady(read));
67
+ onMounted(read);
68
+
69
+ return ready;
70
+ }
package/types/index.d.ts CHANGED
@@ -22,11 +22,22 @@ import type { MarkdownImportConfig } from '@bloklabs/core/markdown';
22
22
  * plus a reactive `width` prop.
23
23
  *
24
24
  * Reactive props (sync after mount without recreation):
25
- * - `readOnly` — calls `editor.readOnly.set(value)`
25
+ * - `readOnly` — calls `editor.readOnly.set(enabled, { hideControls })`; the
26
+ * object form's `hideControls` is live too (toggles in place — see
27
+ * `editor.readOnly.togglesInPlace`)
28
+ * - `hideToolbar` — calls `editor.toolbar.setHidden(value)` (undefined → false)
29
+ * - `inlineToolbar` — calls `editor.tools.setInlineToolbar(value)`
30
+ * (content-compared, so a fresh array with the same names is a no-op)
26
31
  * - `autofocus` — calls `editor.focus()` when changed to true
27
32
  * - `theme` — calls `editor.theme.set(value)`
28
33
  * - `width` — calls `editor.width.set(value)`
29
34
  * - `placeholder` — calls `editor.placeholder.set(value)`
35
+ * - `style.tokens` — calls `editor.tokens.set(value)` (deep-equal–deduped;
36
+ * replace semantics, so pass the complete token set on each change)
37
+ * - `i18n` — calls `editor.i18n.update({ locale, messages, direction })`
38
+ * (deep-equal–deduped; relabels the editor chrome in place, so caret, focus
39
+ * and undo history survive a language switch). `defaultLocale` is not
40
+ * forwarded — it only affects the initial locale resolution.
30
41
  * - `data` — re-renders via `editor.render(value)` when content changes
31
42
  * (deep-equal–deduped and serialized; seeds the initial content at creation)
32
43
  *
@@ -437,6 +448,48 @@ export interface UseBlocksApi {
437
448
  */
438
449
  export declare function useBlocks(editor: MaybeRefOrGetter<Blok | null>): UseBlocksApi;
439
450
 
451
+ /** Options accepted by {@link useBlokReady}. */
452
+ export interface UseBlokReadyOptions {
453
+ /**
454
+ * Restrict the wait to editors mounted inside this element. Accepts the
455
+ * template ref you already hold on the container (or a getter); it is
456
+ * re-read on every readiness change, so a ref that fills in on mount is
457
+ * picked up.
458
+ *
459
+ * Omit it to observe every editor on the page. Passing it while it still
460
+ * resolves to null reports NOT ready — an unresolved scope must never fall
461
+ * back to the page-global one.
462
+ */
463
+ within?: MaybeRefOrGetter<Element | null | undefined>;
464
+ /**
465
+ * `'ready'` (default) settles when each editor has finished booting.
466
+ * `'rendered'` also waits for its content to be in the DOM and re-arms on
467
+ * every post-boot re-render.
468
+ */
469
+ settleOn?: 'ready' | 'rendered';
470
+ }
471
+
472
+ /**
473
+ * Composable exposing the live readiness of the Blok editors in a DOM scope as
474
+ * a boolean ref. Mirrors React's `useBlokReady` and Angular's
475
+ * `injectBlokReady` — all three wrap the same core registry, so they cannot
476
+ * drift.
477
+ *
478
+ * The ref starts `false` and takes its first real reading on mount, once the
479
+ * template ref has filled in. Editors mounted later re-close the gate, and with
480
+ * `settleOn: 'rendered'` so does every re-render. A scope holding no editors is
481
+ * ready.
482
+ *
483
+ * @param options - scope and readiness depth
484
+ *
485
+ * @example
486
+ * ```ts
487
+ * const list = ref<HTMLElement | null>(null);
488
+ * const ready = useBlokReady({ within: list, settleOn: 'rendered' });
489
+ * ```
490
+ */
491
+ export declare function useBlokReady(options?: UseBlokReadyOptions): Readonly<ShallowRef<boolean>>;
492
+
440
493
  /** One field of a {@link CreateVueBlockSpec.propSchema}. */
441
494
  export interface PropSchemaEntry {
442
495
  default: unknown;