@bloklabs/vue 1.15.2 → 1.16.1

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/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)}var s=new WeakMap;function c(e,t){s.set(e,t)}function l(e){return s.get(e)}function u(e){s.delete(e)}function d(e){"@babel/helpers - typeof";return d=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},d(e)}function f(e,t){if(d(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(d(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function p(e){var t=f(e,`string`);return d(t)==`symbol`?t:t+``}function m(e,t,n){return(t=p(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function h(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 g(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?h(Object(n),!0).forEach(function(t){m(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):h(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var _=Symbol(`BLOK_DEFAULT_CONFIG`);function v(t){(0,e.provide)(_,t)}function y(){return(0,e.inject)(_,{})}function b(e,t){if(Object.keys(e).length===0)return t;let n=g({},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=g(g({},e.tools),t.tools)),n}var x=`__blokPortalRegistry`,S=()=>{let t=(0,e.reactive)(new Map);return{entries:t,register(n,r){t.set(n,(0,e.markRaw)(r))},unregister(e,n){var r;(n===void 0||((r=t.get(e))==null?void 0:r.hostEl)===n)&&t.delete(e)},setProps(e,n){let r=t.get(e);r!==void 0&&Object.assign(r.props,n)}}},C=new WeakMap;function w(e,t){C.set(e,t)}function T(e){return C.get(e)}function E(e){C.delete(e)}var D=e=>({onChange:e.onChange!==void 0,onSave:e.onSave!==void 0,onEnter:e.onEnter!==void 0,onSubmit:e.onSubmit!==void 0,onBeforeRender:e.onBeforeRender!==void 0,onAfterRender:e.onAfterRender!==void 0}),O=e=>`[Blok] \`data\` is ignored while collaboration is on: the document lives on the sync service and is shared with everyone editing it, so replacing it from this editor would overwrite their work. To replace the whole document, call POST /sync/${e==null?`{doc}`:e}/reset on your server — it reloads the document from your own document endpoint and every open editor picks it up. To change part of it, use the blocks API (insert/update/delete).`,k=(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}:g({},a);o.config=g(g({},(r=o.config)==null?{}:r),{},{[x]:t}),n[i]=o}return n};function A(r,a){let s=(0,e.shallowRef)(null),l=(0,e.inject)(_,{}),d=()=>b(l,(0,e.toValue)(r)),f={current:null,holder:null,lastRenderedData:d().data,seededEditor:null,renderChain:Promise.resolve(),collaborationWarned:!1,constructedCollaboration:void 0,appliedHandlerPresence:{onChange:!1,onSave:!1,onEnter:!1,onSubmit:!1,onBeforeRender:!1,onAfterRender:!1}},p={onChange:(...e)=>{var t,n;(t=(n=d()).onChange)==null||t.call(n,...e)},onSave:(...e)=>{var t,n;f.lastRenderedData=e[0],(t=(n=d()).onSave)==null||t.call(n,...e)},onEnter:(...e)=>{var t,n;return(t=(n=d()).onEnter)==null?void 0:t.call(n,...e)},onSubmit:(...e)=>{var t,n;(t=(n=d()).onSubmit)==null||t.call(n,...e)},onBeforeRender:(...e)=>{var t,n,r;return(t=(n=(r=d()).onBeforeRender)==null?void 0:n.call(r,...e))==null?e[0]:t},onAfterRender:(...e)=>{var t,n;(t=(n=d()).onAfterRender)==null||t.call(n,...e)}},m=()=>{let t=g({},b((0,e.toRaw)(l),(0,e.toRaw)((0,e.toValue)(r))));return delete t.holder,t.data!==void 0&&(t.data=(0,e.toRaw)(t.data)),t},h=()=>{if(f.current!==null){u(f.current),E(f.current),o(f.current);try{f.current.destroy()}catch(e){}}f.current=null,f.holder=null,s.value=null},v=()=>{let e=document.createElement(`div`);f.holder=e;let n=m(),r=S();n.tools!==void 0&&(n.tools=k(n.tools,r));let a=D(d());n.onChange=a.onChange?p.onChange:void 0,n.onSave=a.onSave?p.onSave:void 0,n.onEnter=a.onEnter?p.onEnter:void 0,n.onSubmit=a.onSubmit?p.onSubmit:void 0,n.onBeforeRender=a.onBeforeRender?p.onBeforeRender:void 0,n.onAfterRender=a.onAfterRender?p.onAfterRender:void 0,f.appliedHandlerPresence=a;let o=new t.Blok(g(g({},n),{},{holder:e}));f.current=o,f.constructedCollaboration=n.collaboration,c(o,e),w(o,r),i(o,{markRendered:e=>{f.lastRenderedData=e}}),o.isReady.then(()=>{f.current===o&&(s.value=o)}).catch(()=>{f.current===o&&h()})};(0,e.watch)([s,()=>(0,n.normalizeReadOnlyConfig)(d().readOnly).enabled,()=>(0,n.normalizeReadOnlyConfig)(d().readOnly).hideControls,()=>typeof d().readOnly==`object`],([e,t,n,r])=>{e&&(r?e.readOnly.set(t,{hideControls:n}):e.readOnly.set(t))},{immediate:!0}),(0,e.watch)([s,()=>d().hideToolbar],([e,t])=>{e&&e.toolbar.setHidden(!!t)},{immediate:!0}),(0,e.watch)([s,()=>d().toolbarPosition],([e,t])=>{e&&t!==void 0&&e.toolbar.setPosition(t)},{immediate:!0}),(0,e.watch)([s,()=>d().theme],([e,t])=>{e&&t!==void 0&&e.theme.set(t)},{immediate:!0}),(0,e.watch)([s,()=>d().width],([e,t])=>{e&&t!==void 0&&e.width.set(t)},{immediate:!0}),(0,e.watch)([s,()=>d().placeholder],([e,t])=>{e&&t!==void 0&&e.placeholder.set(t)},{immediate:!0});let y={value:void 0};(0,e.watch)([s,()=>{var e;return(e=d().style)==null?void 0:e.tokens}],([e,t])=>{!e||t===void 0||(0,n.deepEqual)(t,y.value)||(y.value=g({},t),e.tokens.set(t))},{immediate:!0,deep:!0});let x={value:d().i18n};(0,e.watch)([s,()=>d().i18n],([e,t])=>{if(!e||t===void 0||(0,n.deepEqual)(t,x.value))return;x.value=g({},t);let{locale:r,messages:i,direction:a}=t;e.i18n.update(g(g(g({},r===void 0?{}:{locale:r}),i===void 0?{}:{messages:i}),a===void 0?{}:{direction:a}))},{immediate:!0,deep:!0});let C={editor:null,value:void 0};return(0,e.watch)([s,()=>d().inlineToolbar],([e,t])=>{if(!e||t===void 0||C.editor===e&&(0,n.deepEqual)(t,C.value))return;let r=Array.isArray(t)?[...t]:t;C.editor=e,C.value=r,e.tools.setInlineToolbar(r)},{immediate:!0,deep:!0}),(0,e.watch)([s,()=>d().autofocus],([e,t])=>{e&&t&&e.focus()},{immediate:!0}),(0,e.watch)([s,()=>JSON.stringify(D(d()))],([e])=>{if(!e)return;let t=D(d()),n=f.appliedHandlerPresence,r={},i={value:!1},a=(e,r)=>{t[e]!==n[e]&&(n[e]=t[e],i.value=!0,r(t[e]?p[e]:void 0))};a(`onChange`,e=>{r.onChange=e}),a(`onSave`,e=>{r.onSave=e}),a(`onEnter`,e=>{r.onEnter=e}),a(`onSubmit`,e=>{r.onSubmit=e}),a(`onBeforeRender`,e=>{r.onBeforeRender=e}),a(`onAfterRender`,e=>{r.onAfterRender=e}),i.value&&e.handlers.set(r)},{immediate:!0}),(0,e.watch)([s,()=>d().data],([t,r])=>{if(!t||r===void 0)return;if(f.seededEditor!==t){f.seededEditor=t,f.lastRenderedData=r;return}let i=f.lastRenderedData;if(i!==void 0&&(0,n.equalsOutputData)(r,i))return;let a=f.constructedCollaboration;if(a!==void 0){f.collaborationWarned||(f.collaborationWarned=!0,console.warn(O(a.doc)));return}f.lastRenderedData=r,f.renderChain=f.renderChain.catch(()=>void 0).then(()=>t.render((0,n.toRenderableData)((0,e.toRaw)(r))))},{immediate:!0}),a!==void 0&&(0,e.watch)(()=>(0,e.toValue)(a),()=>{h(),v()}),(0,e.onMounted)(v),(0,e.onBeforeUnmount)(h),s}var j=`block changed`;function M(t,r={}){let i=(0,e.shallowRef)(0),a=()=>{let n=(0,e.toValue)(t);return n===null?null:(0,e.toRaw)(n)},o=()=>{i.value},s=(0,e.shallowRef)(n.EMPTY_API),c={editor:null,handler:null},l=()=>{c.editor!==null&&c.handler!==null&&c.editor.off(j,c.handler),c.editor=null,c.handler=null};return(0,e.watch)(()=>a(),t=>{if(l(),i.value+=1,t===null){s.value=n.EMPTY_API;return}let a=a=>{var o;let s=(o=(0,e.toValue)(r.within))==null?null:o;s!==null&&!(0,n.changeTouchesSubtree)(t,a,s)||(i.value+=1)};t.on(j,a),c.editor=t,c.handler=a,s.value=(0,n.createBlocksApiForEditor)(t,o)},{immediate:!0}),(0,e.onScopeDispose)(l),{getById:e=>s.value.getById(e),getChildren:e=>s.value.getChildren(e),insert:e=>s.value.insert(e),insertMany:e=>s.value.insertMany(e),insertTree:e=>s.value.insertTree(e),insertMarkdown:(e,t)=>s.value.insertMarkdown(e,t),exportMarkdown:()=>s.value.exportMarkdown(),move:(e,t)=>s.value.move(e,t),nest:(e,t)=>s.value.nest(e,t),unnest:e=>s.value.unnest(e),remove:e=>s.value.remove(e),update:(e,t,n)=>s.value.update(e,t,n),convert:(e,t,n,r)=>s.value.convert(e,t,n,r),transact:e=>s.value.transact(e),transactWithoutCapture:e=>s.value.transactWithoutCapture(e),getBlocksCount:()=>s.value.getBlocksCount(),getCurrentBlockIndex:()=>s.value.getCurrentBlockIndex(),getBlockByIndex:e=>s.value.getBlockByIndex(e),getBlockByElement:e=>s.value.getBlockByElement(e),getBlockData:e=>s.value.getBlockData(e),getBlockIndex:e=>s.value.getBlockIndex(e),composeBlockData:e=>s.value.composeBlockData(e),renderFromHTML:e=>s.value.renderFromHTML(e),insertOutputData:(e,t)=>s.value.insertOutputData(e,t),splitBlock:(e,t,n,r,i)=>s.value.splitBlock(e,t,n,r,i),insertInsideParent:(e,t,n)=>s.value.insertInsideParent(e,t,n),render:e=>s.value.render(e),clear:()=>s.value.clear(),isSyncingFromYjs:()=>s.value.isSyncingFromYjs()}}function N(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 P=(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)}}}),F=(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)(P,null,{default:()=>(0,e.h)(n.component,n.props)})])))}}),I=Symbol(`BLOK_EDITOR_INSTANCE`),L=(0,e.shallowRef)(null);function R(){return(0,e.inject)(I,L)}var z=(0,e.defineComponent)({name:`BlokContent`,props:{editor:{type:Object,default:null}},setup(t){let n=(0,e.ref)(null);(0,e.provide)(I,(0,e.computed)(()=>t.editor===null?null:(0,e.toRaw)(t.editor)));let r=t=>{if(n.value===null||t===null)return;let r=l((0,e.toRaw)(t));r!==void 0&&n.value.appendChild(r)},i=t=>{var n;t!==null&&((n=l((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:T((0,e.toRaw)(r));return(0,e.h)(`div`,{ref:n},i===void 0?[]:[(0,e.h)(F,{registry:i})])}}}),B=`autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.toolbarPosition.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.inlineEmoji.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter.onSubmit.onError.migrations.uploader.server.ticket.persistence.collaboration.captureClicksBelowEditor`.split(`.`),V=(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},toolbarPosition:{type:String,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},inlineEmoji:{type: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},onSubmit:{type:Function,default:void 0},onError:{type:Function,default:void 0},migrations:{type:Object,default:void 0},uploader:{type:Object,default:void 0},server:{type:String,default:void 0},ticket:{type:String,default:void 0},persistence:{type:Object,default:void 0},collaboration:{type:Object,default:void 0},captureClicksBelowEditor:{type:Boolean,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 o=(0,e.getCurrentInstance)(),s=()=>{let e=o==null?void 0:o.vnode.props;return e==null?``:Object.keys(e).filter(e=>e.startsWith(`on`)).sort().join(`|`)},c=(0,e.ref)(s());(0,e.onUpdated)(()=>{c.value=s()});let l=e=>c.value.split(`|`).includes(e),u=()=>{let e={};for(let n of B){let r=t[n];r!==void 0&&(e[n]=r)}return l(`onChange`)&&(e.onChange=(e,t)=>{n(`change`,{api:e,event:t})}),(l(`onSave`)||l(`onUpdate:data`))&&(e.onSave=e=>{n(`update:data`,e),n(`save`,e)}),l(`onAfterRender`)&&(e.onAfterRender=e=>{n(`after-render`,e)}),l(`onThemeChange`)&&(e.onThemeChange=e=>{n(`theme-change`,e)}),e},d=A(()=>u(),()=>t.recreateKey);(0,e.watch)([d,c],([e],t,r)=>{if(e===null)return;let i=[];if(l(`onBlocksRendered`)){let t=e=>n(`blocks-rendered`,e);e.on(`blocks:rendered`,t),i.push([`blocks:rendered`,t])}if(l(`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 f={last:null};return(0,e.watch)(d,e=>{e!==null&&e!==f.last&&(f.last=e,n(`ready`,e))}),r({instance:(0,e.computed)(()=>d.value),save:()=>{var e;return(e=d.value)==null?void 0:e.save()},focus:e=>{var t;(t=d.value)==null||t.focus(e)},render:e=>{let t=d.value;if(t!==null)return t.render(e).then(()=>{var n;(n=a(t))==null||n.markRendered(e)})}}),()=>(0,e.h)(z,g({editor:d.value},i))}}),H=[`toolbox`,`isReadOnlySupported`,`__isBlokVueBlock`],U=new Set([void 0,`user`,`api`,`convert`]),W=(e,t,r)=>{var i;e==null||(i=e.events)==null||i.emit(n.BlockChildrenMounted,{blockId:t,childIds:r.map(e=>e.id)})};function G(t){var r,i;let a=()=>(0,e.defineComponent)({name:`VueBlock(${t.type})`,props:{ctx:{type:Object,required:!0},notifyMounted:{type:Function,default:void 0}},setup(n){return(0,e.onMounted)(()=>{var e;return(e=n.notifyMounted)==null?void 0:e.call(n)}),t.setup(n.ctx)}}),o=(r=class{static get toolbox(){return t.toolbox}static get isReadOnlySupported(){return!0}constructor(r){var i,o,s;this.wrappedComponent=a(),this.mountSignalled=!1,this.hostEl=null,this.pendingDispatch=!1,this.anchorEl=null,this.toolbarAnchorRef=e=>{let t=e===null||e instanceof Element?e:e.$el;this.anchorEl=t instanceof HTMLElement?t:null},this.notifyMounted=()=>{var e;if(this.mountSignalled)return;this.mountSignalled=!0;let n={origin:this.origin,api:this.api};if((e=t.onMounted)==null||e.call(t,this.blockApi,n),U.has(this.origin)){var r;(r=t.onCreated)==null||r.call(t,this.blockApi,n)}},this.commit=e=>{let r=(0,n.fillDefaults)(t.propSchema,g(g({},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 c=(i=r.config)==null?{}:i;this.registry=c[x],this.api=r.api;let l=r.api;this.pointerDrag=()=>{var e;return(l==null||(e=l.blocks)==null?void 0:e.isPointerDragActive)===!0},this.mirror=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)((o=r.data)==null?{}:o)),this.lastRendered=this.mirror,this.dataRef=(0,e.shallowRef)(this.mirror),this.readOnlyRef=(0,e.shallowRef)(r.readOnly),this.origin=(s=r.origin)==null?`api`:s;let u=this.blockApi,d=this.api;this.childrenComponent=(0,e.defineComponent)({name:`VueBlockChildren(${t.type})`,props:{childAttributes:{type:Function,default:void 0},childContentAttributes:{type:Function,default:void 0}},setup(t){let r=(0,e.ref)(null),i=(0,n.createChildDecorationLedger)(),a=()=>{if(r.value===null)return;let e=u.getChildren();(0,n.mountChildBlocks)(r.value,e),(0,n.applyChildDecoration)(i,e,{childAttributes:t.childAttributes,childContentAttributes:t.childContentAttributes}),W(d,u.id,e)};return(0,e.onMounted)(a),(0,e.onUpdated)(a),()=>(0,e.h)(`div`,{ref:r,[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,api:this.api,readOnly:this.readOnlyRef,BlockChildren:this.childrenComponent,toolbarAnchorRef:this.toolbarAnchorRef};return(e=this.registry)==null||e.register(this.blockApi.id,{hostEl:t,component:this.wrappedComponent,props:{ctx:n,notifyMounted:this.notifyMounted}}),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}getToolbarAnchorElement(){var e;let n=this.anchorEl;if(n!==null&&n.isConnected)return n;let r=this.hostEl;if(r!==null&&t.getToolbarAnchorElement!==void 0)return(e=t.getToolbarAnchorElement(r,this.blockApi))==null?void 0:e}moved(){var e;(e=t.onMoved)==null||e.call(t,this.blockApi)}removed(){var e,n,r;(e=this.registry)==null||e.unregister(this.blockApi.id,(n=this.hostEl)==null?void 0:n),(r=t.onRemoved)==null||r.call(t,this.blockApi)}destroy(){var e,t;(e=this.registry)==null||e.unregister(this.blockApi.id,(t=this.hostEl)==null?void 0:t)}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);for(let[e,n]of Object.entries((i=t.statics)==null?{}:i))H.includes(e)||Object.defineProperty(o,e,{value:n,writable:!0,enumerable:!0,configurable:!0});return o}exports.BLOK_DEFAULT_CONFIG=_,exports.BLOK_EDITOR_INSTANCE=I,exports.BlokContent=z,exports.BlokEditor=V,exports.createVueBlock=G,exports.provideBlok=v,exports.useBlocks=M,exports.useBlok=A,exports.useBlokDefaults=y,exports.useBlokInstance=R,exports.useBlokReady=N;
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)}var s=new WeakMap;function c(e,t){s.set(e,t)}function l(e){return s.get(e)}function u(e){s.delete(e)}function d(e){"@babel/helpers - typeof";return d=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},d(e)}function f(e,t){if(d(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(d(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function p(e){var t=f(e,`string`);return d(t)==`symbol`?t:t+``}function m(e,t,n){return(t=p(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function h(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 g(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?h(Object(n),!0).forEach(function(t){m(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):h(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var _=Symbol(`BLOK_DEFAULT_CONFIG`);function v(t){(0,e.provide)(_,t)}function y(){return(0,e.inject)(_,{})}function b(e,t){if(Object.keys(e).length===0)return t;let n=g({},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=g(g({},e.tools),t.tools)),n}var x=`__blokPortalRegistry`,S=()=>{let t=(0,e.reactive)(new Map);return{entries:t,register(n,r){t.set(n,(0,e.markRaw)(r))},unregister(e,n){var r;(n===void 0||((r=t.get(e))==null?void 0:r.hostEl)===n)&&t.delete(e)},setProps(e,n){let r=t.get(e);r!==void 0&&Object.assign(r.props,n)}}},C=new WeakMap;function w(e,t){C.set(e,t)}function T(e){return C.get(e)}function E(e){C.delete(e)}var D=e=>({onChange:e.onChange!==void 0,onSave:e.onSave!==void 0,onEnter:e.onEnter!==void 0,onSubmit:e.onSubmit!==void 0,onBeforeRender:e.onBeforeRender!==void 0,onAfterRender:e.onAfterRender!==void 0}),O=e=>`[Blok] \`data\` is ignored while collaboration is on: the document lives on the sync service and is shared with everyone editing it, so replacing it from this editor would overwrite their work. To replace the whole document, call POST /sync/${e==null?`{doc}`:e}/reset on your server — it reloads the document from your own document endpoint and every open editor picks it up. To change part of it, use the blocks API (insert/update/delete).`,k=(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}:g({},a);o.config=g(g({},(r=o.config)==null?{}:r),{},{[x]:t}),n[i]=o}return n};function A(r,a){let s=(0,e.shallowRef)(null),l=(0,e.inject)(_,{}),d=()=>b(l,(0,e.toValue)(r)),f={current:null,holder:null,lastRenderedData:d().data,pendingData:void 0,seededEditor:null,renderChain:Promise.resolve(),collaborationWarnedFor:null,constructedCollaboration:void 0,appliedHandlerPresence:{onChange:!1,onSave:!1,onEnter:!1,onSubmit:!1,onBeforeRender:!1,onAfterRender:!1}},p=(0,n.createEmittedEchoWindow)(),m={onChange:(...e)=>{var t,n;(t=(n=d()).onChange)==null||t.call(n,...e)},onSave:(...e)=>{var t,n;f.lastRenderedData=e[0],p.record(e[0]),(t=(n=d()).onSave)==null||t.call(n,...e)},onEnter:(...e)=>{var t,n;return(t=(n=d()).onEnter)==null?void 0:t.call(n,...e)},onSubmit:(...e)=>{var t,n;(t=(n=d()).onSubmit)==null||t.call(n,...e)},onBeforeRender:(...e)=>{var t,n,r;return(t=(n=(r=d()).onBeforeRender)==null?void 0:n.call(r,...e))==null?e[0]:t},onAfterRender:(...e)=>{var t,n;(t=(n=d()).onAfterRender)==null||t.call(n,...e)}},h=()=>{let t=g({},b((0,e.toRaw)(l),(0,e.toRaw)((0,e.toValue)(r))));return delete t.holder,t.data!==void 0&&(t.data=(0,e.toRaw)(t.data)),t},v=()=>{if(f.current!==null){u(f.current),E(f.current),o(f.current);try{f.current.destroy()}catch(e){}}f.current=null,f.holder=null,s.value=null},y=()=>{let e=document.createElement(`div`);f.holder=e;let n=h(),r=S();n.tools!==void 0&&(n.tools=k(n.tools,r));let a=D(d());n.onChange=a.onChange?m.onChange:void 0,n.onSave=a.onSave?m.onSave:void 0,n.onEnter=a.onEnter?m.onEnter:void 0,n.onSubmit=a.onSubmit?m.onSubmit:void 0,n.onBeforeRender=a.onBeforeRender?m.onBeforeRender:void 0,n.onAfterRender=a.onAfterRender?m.onAfterRender:void 0,f.appliedHandlerPresence=a;let o=new t.Blok(g(g({},n),{},{holder:e}));f.current=o,f.constructedCollaboration=n.collaboration,c(o,e),w(o,r),i(o,{markRendered:e=>{p.clear(),f.lastRenderedData=e}}),o.isReady.then(()=>{f.current===o&&(s.value=o)}).catch(()=>{f.current===o&&v()})};(0,e.watch)([s,()=>(0,n.normalizeReadOnlyConfig)(d().readOnly).enabled,()=>(0,n.normalizeReadOnlyConfig)(d().readOnly).hideControls,()=>typeof d().readOnly==`object`],([e,t,n,r])=>{e&&(r?e.readOnly.set(t,{hideControls:n}):e.readOnly.set(t))},{immediate:!0}),(0,e.watch)([s,()=>d().hideToolbar],([e,t])=>{e&&e.toolbar.setHidden(!!t)},{immediate:!0}),(0,e.watch)([s,()=>d().toolbarPosition],([e,t])=>{e&&t!==void 0&&e.toolbar.setPosition(t)},{immediate:!0}),(0,e.watch)([s,()=>d().theme],([e,t])=>{e&&t!==void 0&&e.theme.set(t)},{immediate:!0}),(0,e.watch)([s,()=>d().width],([e,t])=>{e&&t!==void 0&&e.width.set(t)},{immediate:!0}),(0,e.watch)([s,()=>d().placeholder],([e,t])=>{e&&t!==void 0&&e.placeholder.set(t)},{immediate:!0});let x={value:void 0};(0,e.watch)([s,()=>{var e;return(e=d().style)==null?void 0:e.tokens}],([e,t])=>{e&&t!==void 0&&!(0,n.deepEqual)(t,x.value)&&(x.value=g({},t),e.tokens.set(t))},{immediate:!0,deep:!0});let C={value:d().i18n};(0,e.watch)([s,()=>d().i18n],([e,t])=>{let r=C.value;if(!e||t===void 0&&(r==null?void 0:r.direction)===void 0||(0,n.deepEqual)(t,r))return;C.value=t===void 0?void 0:g({},t);let{locale:i,messages:a,direction:o}=t==null?{}:t,s=o==null?(r==null?void 0:r.direction)===void 0?void 0:null:o;e.i18n.update(g(g(g({},i===void 0?{}:{locale:i}),a===void 0?{}:{messages:a}),s===void 0?{}:{direction:s}))},{immediate:!0,deep:!0});let T={editor:null,value:void 0};return(0,e.watch)([s,()=>d().inlineToolbar],([e,t])=>{if(!e||t===void 0||T.editor===e&&(0,n.deepEqual)(t,T.value))return;let r=Array.isArray(t)?[...t]:t;T.editor=e,T.value=r,e.tools.setInlineToolbar(r)},{immediate:!0,deep:!0}),(0,e.watch)([s,()=>d().autofocus],([e,t])=>{e&&t&&e.focus()},{immediate:!0}),(0,e.watch)([s,()=>JSON.stringify(D(d()))],([e])=>{if(!e)return;let t=D(d()),n=f.appliedHandlerPresence,r={},i={value:!1},a=(e,r)=>{t[e]!==n[e]&&(n[e]=t[e],i.value=!0,r(t[e]?m[e]:void 0))};a(`onChange`,e=>{r.onChange=e}),a(`onSave`,e=>{r.onSave=e}),a(`onEnter`,e=>{r.onEnter=e}),a(`onSubmit`,e=>{r.onSubmit=e}),a(`onBeforeRender`,e=>{r.onBeforeRender=e}),a(`onAfterRender`,e=>{r.onAfterRender=e}),i.value&&e.handlers.set(r)},{immediate:!0}),(0,e.watch)([s,()=>d().data],([t,r])=>{if(!t||r===void 0)return;if(f.seededEditor!==t){f.seededEditor=t,f.lastRenderedData=r,f.pendingData=void 0,p.clear();return}let i=f.lastRenderedData,a=f.pendingData;if(i!==void 0&&(0,n.equalsOutputData)(r,i)||a!==void 0&&(0,n.equalsOutputData)(r,a)||p.matches(r))return;let o=f.constructedCollaboration;if(o!==void 0){f.collaborationWarnedFor!==t&&(f.collaborationWarnedFor=t,console.warn(O(o.doc)));return}p.clear(),f.pendingData=r,f.renderChain=f.renderChain.then(()=>t.render((0,n.toRenderableData)((0,e.toRaw)(r)))).then(()=>{f.lastRenderedData=r},()=>void 0).then(()=>{f.pendingData===r&&(f.pendingData=void 0)})},{immediate:!0}),a!==void 0&&(0,e.watch)(()=>(0,e.toValue)(a),()=>{v(),y()}),(0,e.onMounted)(y),(0,e.onBeforeUnmount)(v),s}var j=`block changed`;function M(t,r={}){let i=(0,e.shallowRef)(0),a=()=>{let n=(0,e.toValue)(t);return n===null?null:(0,e.toRaw)(n)},o=()=>{i.value},s=(0,e.shallowRef)(n.EMPTY_API),c={editor:null,handler:null},l=()=>{c.editor!==null&&c.handler!==null&&c.editor.off(j,c.handler),c.editor=null,c.handler=null};return(0,e.watch)(()=>a(),t=>{if(l(),i.value+=1,t===null){s.value=n.EMPTY_API;return}let a=a=>{var o;let s=(o=(0,e.toValue)(r.within))==null?null:o;(s===null||(0,n.changeTouchesSubtree)(t,a,s))&&(i.value+=1)};t.on(j,a),c.editor=t,c.handler=a,s.value=(0,n.createBlocksApiForEditor)(t,o)},{immediate:!0}),(0,e.onScopeDispose)(l),{getById:e=>s.value.getById(e),getChildren:e=>s.value.getChildren(e),insert:e=>s.value.insert(e),insertMany:e=>s.value.insertMany(e),insertTree:e=>s.value.insertTree(e),insertMarkdown:(e,t)=>s.value.insertMarkdown(e,t),exportMarkdown:()=>s.value.exportMarkdown(),move:(e,t)=>s.value.move(e,t),nest:(e,t)=>s.value.nest(e,t),unnest:e=>s.value.unnest(e),remove:e=>s.value.remove(e),update:(e,t,n)=>s.value.update(e,t,n),convert:(e,t,n,r)=>s.value.convert(e,t,n,r),transact:e=>s.value.transact(e),transactWithoutCapture:(e,t)=>s.value.transactWithoutCapture(e,t),getBlocksCount:()=>s.value.getBlocksCount(),getCurrentBlockIndex:()=>s.value.getCurrentBlockIndex(),getBlockByIndex:e=>s.value.getBlockByIndex(e),getBlockByElement:e=>s.value.getBlockByElement(e),getBlockData:e=>s.value.getBlockData(e),getBlockIndex:e=>s.value.getBlockIndex(e),composeBlockData:e=>s.value.composeBlockData(e),renderFromHTML:e=>s.value.renderFromHTML(e),insertOutputData:(e,t)=>s.value.insertOutputData(e,t),splitBlock:(e,t,n,r,i)=>s.value.splitBlock(e,t,n,r,i),insertInsideParent:(e,t,n)=>s.value.insertInsideParent(e,t,n),render:e=>s.value.render(e),clear:()=>s.value.clear(),isSyncingFromYjs:()=>s.value.isSyncingFromYjs()}}function N(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 P=(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)}}}),F=(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)(P,null,{default:()=>(0,e.h)(n.component,n.props)})])))}}),I=Symbol(`BLOK_EDITOR_INSTANCE`),L=(0,e.shallowRef)(null);function R(){return(0,e.inject)(I,L)}var z=(0,e.defineComponent)({name:`BlokContent`,props:{editor:{type:Object,default:null}},setup(t){let n=(0,e.ref)(null);(0,e.provide)(I,(0,e.computed)(()=>t.editor===null?null:(0,e.toRaw)(t.editor)));let r=t=>{if(n.value===null||t===null)return;let r=l((0,e.toRaw)(t));r!==void 0&&n.value.appendChild(r)},i=t=>{var n;t!==null&&((n=l((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:T((0,e.toRaw)(r));return(0,e.h)(`div`,{ref:n},i===void 0?[]:[(0,e.h)(F,{registry:i})])}}}),B=`autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.toolbarPosition.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.loader.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.inlineEmoji.find.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter.onSubmit.onError.onImageFailure.migrations.uploader.media.server.ticket.persistence.collaboration.documentId.tabSync.captureClicksBelowEditor`.split(`.`),V=(e,t,n)=>{let r=t.flatMap(t=>{var n;return(n=e==null?void 0:e[t])==null?[]:n});for(let e of r)typeof e==`function`&&e(n)},H=(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},toolbarPosition:{type:String,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},loader:{type:[Boolean,Object],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},inlineEmoji:{type:Boolean,default:void 0},find:{type:[Boolean,Object],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},onSubmit:{type:Function,default:void 0},onError:{type:Function,default:void 0},onImageFailure:{type:Function,default:void 0},migrations:{type:Object,default:void 0},uploader:{type:Object,default:void 0},media:{type:Object,default:void 0},server:{type:String,default:void 0},ticket:{type:String,default:void 0},persistence:{type:Object,default:void 0},collaboration:{type:Object,default:void 0},documentId:{type:String,default:void 0},tabSync:{type:[Boolean,Object],default:void 0},captureClicksBelowEditor:{type:Boolean,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 o=(0,e.getCurrentInstance)(),s=()=>{let e=o==null?void 0:o.vnode.props;return e==null?``:Object.keys(e).filter(e=>e.startsWith(`on`)).sort().join(`|`)},c=(0,e.ref)(s());(0,e.onUpdated)(()=>{c.value=s()});let l=e=>c.value.split(`|`).includes(e),u=()=>{let e={};for(let n of B){let r=t[n];r!==void 0&&(e[n]=r)}return l(`onChange`)&&(e.onChange=(e,t)=>{n(`change`,{api:e,event:t})}),(l(`onSave`)||l(`onUpdate:data`))&&(e.onSave=e=>{if((o==null?void 0:o.isUnmounted)===!0){V(o.vnode.props,[`onUpdate:data`,`onSave`],e);return}n(`update:data`,e),n(`save`,e)}),l(`onAfterRender`)&&(e.onAfterRender=e=>{n(`after-render`,e)}),l(`onThemeChange`)&&(e.onThemeChange=e=>{n(`theme-change`,e)}),e},d=A(()=>u(),()=>t.recreateKey);(0,e.watch)([d,c],([e],t,r)=>{if(e===null)return;let i=[];if(l(`onBlocksRendered`)){let t=e=>n(`blocks-rendered`,e);e.on(`blocks:rendered`,t),i.push([`blocks:rendered`,t])}if(l(`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 f={last:null};return(0,e.watch)(d,e=>{e!==null&&e!==f.last&&(f.last=e,n(`ready`,e))}),r({instance:(0,e.computed)(()=>d.value),save:()=>{var e;return(e=d.value)==null?void 0:e.save()},confirmLeave:()=>{var e,t;return(e=(t=d.value)==null?void 0:t.confirmLeave())==null?Promise.resolve(!0):e},focus:e=>{var t;(t=d.value)==null||t.focus(e)},render:e=>{let t=d.value;if(t!==null)return t.render(e).then(()=>{var n;(n=a(t))==null||n.markRendered(e)})}}),()=>(0,e.h)(z,g({editor:d.value},i))}}),U=[`toolbox`,`isReadOnlySupported`,`__isBlokVueBlock`],W=new Set([void 0,`user`,`api`,`convert`]),G=(e,t,r)=>{var i;e==null||(i=e.events)==null||i.emit(n.BlockChildrenMounted,{blockId:t,childIds:r.map(e=>e.id)})};function K(t){var r,i;let a=()=>(0,e.defineComponent)({name:`VueBlock(${t.type})`,props:{ctx:{type:Object,required:!0},notifyMounted:{type:Function,default:void 0}},setup(n){return(0,e.onMounted)(()=>{var e;return(e=n.notifyMounted)==null?void 0:e.call(n)}),t.setup(n.ctx)}}),o=(r=class{static get toolbox(){return t.toolbox}static get isReadOnlySupported(){return!0}constructor(r){var i,o,s;this.wrappedComponent=a(),this.mountSignalled=!1,this.hostEl=null,this.pendingDispatch=!1,this.anchorEl=null,this.toolbarAnchorRef=e=>{let t=e===null||e instanceof Element?e:e.$el;this.anchorEl=t instanceof HTMLElement?t:null},this.notifyMounted=()=>{var e;if(this.mountSignalled)return;this.mountSignalled=!0;let n={origin:this.origin,api:this.api};if((e=t.onMounted)==null||e.call(t,this.blockApi,n),W.has(this.origin)){var r;(r=t.onCreated)==null||r.call(t,this.blockApi,n)}},this.commit=e=>{let r=(0,n.fillDefaults)(t.propSchema,g(g({},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 c=(i=r.config)==null?{}:i;this.registry=c[x],this.api=r.api;let l=r.api;this.pointerDrag=()=>{var e;return(l==null||(e=l.blocks)==null?void 0:e.isPointerDragActive)===!0},this.mirror=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)((o=r.data)==null?{}:o)),this.lastRendered=this.mirror,this.dataRef=(0,e.shallowRef)(this.mirror),this.readOnlyRef=(0,e.shallowRef)(r.readOnly),this.origin=(s=r.origin)==null?`api`:s;let u=this.blockApi,d=this.api;this.childrenComponent=(0,e.defineComponent)({name:`VueBlockChildren(${t.type})`,props:{childAttributes:{type:Function,default:void 0},childContentAttributes:{type:Function,default:void 0}},setup(t){let r=(0,e.ref)(null),i=(0,n.createChildDecorationLedger)(),a=()=>{if(r.value===null)return;let e=u.getChildren();(0,n.mountChildBlocks)(r.value,(0,n.withSlotlessDescendants)(e,e=>d.blocks.getChildren(e))),(0,n.applyChildDecoration)(i,e,{childAttributes:t.childAttributes,childContentAttributes:t.childContentAttributes}),G(d,u.id,e)};return(0,e.onMounted)(a),(0,e.onUpdated)(a),()=>(0,e.h)(`div`,{ref:r,[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,api:this.api,readOnly:this.readOnlyRef,BlockChildren:this.childrenComponent,toolbarAnchorRef:this.toolbarAnchorRef};return(e=this.registry)==null||e.register(this.blockApi.id,{hostEl:t,component:this.wrappedComponent,props:{ctx:n,notifyMounted:this.notifyMounted}}),t}rendered(){var e;(e=t.onRendered)==null||e.call(t,this.blockApi)}save(){return this.mirror}async setData(r){let i=(0,n.fillDefaults)(t.propSchema,(0,e.toRaw)(r==null?{}:r));return(0,n.deepEqual)(i,this.lastRendered)?!0:(this.mirror=i,this.lastRendered=i,this.dataRef.value=i,await(0,e.nextTick)(),!0)}setReadOnly(e){this.readOnlyRef.value=e}getToolbarAnchorElement(){var e;let n=this.anchorEl;if(n!==null&&n.isConnected)return n;let r=this.hostEl;if(r!==null&&t.getToolbarAnchorElement!==void 0)return(e=t.getToolbarAnchorElement(r,this.blockApi))==null?void 0:e}onNavigationEnter(e){var n;return((n=t.onNavigationEnter)==null?void 0:n.call(t,e,this.blockApi))===!0}moved(){var e;(e=t.onMoved)==null||e.call(t,this.blockApi)}removed(){var e,n,r;(e=this.registry)==null||e.unregister(this.blockApi.id,(n=this.hostEl)==null?void 0:n),(r=t.onRemoved)==null||r.call(t,this.blockApi)}destroy(){var e,t;(e=this.registry)==null||e.unregister(this.blockApi.id,(t=this.hostEl)==null?void 0:t)}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);for(let[e,n]of Object.entries((i=t.statics)==null?{}:i))U.includes(e)||Object.defineProperty(o,e,{value:n,writable:!0,enumerable:!0,configurable:!0});return o}exports.BLOK_DEFAULT_CONFIG=_,exports.BLOK_EDITOR_INSTANCE=I,exports.BlokContent=z,exports.BlokEditor=H,exports.createVueBlock=K,exports.provideBlok=v,exports.useBlocks=M,exports.useBlok=A,exports.useBlokDefaults=y,exports.useBlokInstance=R,exports.useBlokReady=N;
package/dist/index.mjs CHANGED
@@ -1,61 +1,61 @@
1
1
  import { Fragment as e, Teleport as t, computed as n, defineComponent as r, getCurrentInstance as i, h as a, inject as o, markRaw as s, nextTick as c, onBeforeUnmount as l, onErrorCaptured as u, onMounted as d, onScopeDispose as f, onUpdated as p, provide as m, reactive as h, ref as g, shallowRef as _, toRaw as v, toValue as y, watch as b } from "vue";
2
2
  import { Blok as x } from "@bloklabs/core";
3
- import { BlockChildrenMounted as S, DATA_ATTR as C, EMPTY_API as w, applyChildDecoration as T, changeTouchesSubtree as ee, createBlocksApiForEditor as te, createChildDecorationLedger as ne, deepEqual as E, equalsOutputData as D, fillDefaults as O, mountChildBlocks as k, normalizeReadOnlyConfig as A, toRenderableData as j } from "@bloklabs/core/adapters";
3
+ import { BlockChildrenMounted as S, DATA_ATTR as C, EMPTY_API as w, applyChildDecoration as T, changeTouchesSubtree as E, createBlocksApiForEditor as ee, createChildDecorationLedger as te, createEmittedEchoWindow as ne, deepEqual as D, equalsOutputData as O, fillDefaults as k, mountChildBlocks as A, normalizeReadOnlyConfig as j, toRenderableData as re, withSlotlessDescendants as ie } from "@bloklabs/core/adapters";
4
4
  //#region src/content-baseline-map.ts
5
5
  var M = /* @__PURE__ */ new WeakMap();
6
- function re(e, t) {
6
+ function ae(e, t) {
7
7
  M.set(e, t);
8
8
  }
9
- function ie(e) {
9
+ function oe(e) {
10
10
  return M.get(e);
11
11
  }
12
- function ae(e) {
12
+ function se(e) {
13
13
  M.delete(e);
14
14
  }
15
15
  //#endregion
16
16
  //#region src/holder-map.ts
17
17
  var N = /* @__PURE__ */ new WeakMap();
18
- function oe(e, t) {
18
+ function ce(e, t) {
19
19
  N.set(e, t);
20
20
  }
21
21
  function P(e) {
22
22
  return N.get(e);
23
23
  }
24
- function se(e) {
24
+ function F(e) {
25
25
  N.delete(e);
26
26
  }
27
27
  //#endregion
28
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/typeof.js
29
- function F(e) {
28
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
29
+ function I(e) {
30
30
  "@babel/helpers - typeof";
31
- return F = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
31
+ return I = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) {
32
32
  return typeof e;
33
33
  } : function(e) {
34
34
  return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
35
- }, F(e);
35
+ }, I(e);
36
36
  }
37
37
  //#endregion
38
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPrimitive.js
39
- function I(e, t) {
40
- if (F(e) != "object" || !e) return e;
38
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
39
+ function L(e, t) {
40
+ if (I(e) != "object" || !e) return e;
41
41
  var n = e[Symbol.toPrimitive];
42
42
  if (n !== void 0) {
43
43
  var r = n.call(e, t || "default");
44
- if (F(r) != "object") return r;
44
+ if (I(r) != "object") return r;
45
45
  throw TypeError("@@toPrimitive must return a primitive value.");
46
46
  }
47
47
  return (t === "string" ? String : Number)(e);
48
48
  }
49
49
  //#endregion
50
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/toPropertyKey.js
51
- function L(e) {
52
- var t = I(e, "string");
53
- return F(t) == "symbol" ? t : t + "";
50
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
51
+ function R(e) {
52
+ var t = L(e, "string");
53
+ return I(t) == "symbol" ? t : t + "";
54
54
  }
55
55
  //#endregion
56
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/defineProperty.js
57
- function R(e, t, n) {
58
- return (t = L(t)) in e ? Object.defineProperty(e, t, {
56
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
57
+ function z(e, t, n) {
58
+ return (t = R(t)) in e ? Object.defineProperty(e, t, {
59
59
  value: n,
60
60
  enumerable: !0,
61
61
  configurable: !0,
@@ -63,8 +63,8 @@ function R(e, t, n) {
63
63
  }) : e[t] = n, e;
64
64
  }
65
65
  //#endregion
66
- //#region \0@oxc-project+runtime@0.147.0/helpers/esm/objectSpread2.js
67
- function z(e, t) {
66
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectSpread2.js
67
+ function B(e, t) {
68
68
  var n = Object.keys(e);
69
69
  if (Object.getOwnPropertySymbols) {
70
70
  var r = Object.getOwnPropertySymbols(e);
@@ -74,12 +74,12 @@ function z(e, t) {
74
74
  }
75
75
  return n;
76
76
  }
77
- function B(e) {
77
+ function V(e) {
78
78
  for (var t = 1; t < arguments.length; t++) {
79
79
  var n = arguments[t] == null ? {} : arguments[t];
80
- t % 2 ? z(Object(n), !0).forEach(function(t) {
81
- R(e, t, n[t]);
82
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : z(Object(n)).forEach(function(t) {
80
+ t % 2 ? B(Object(n), !0).forEach(function(t) {
81
+ z(e, t, n[t]);
82
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : B(Object(n)).forEach(function(t) {
83
83
  Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
84
84
  });
85
85
  }
@@ -87,25 +87,25 @@ function B(e) {
87
87
  }
88
88
  //#endregion
89
89
  //#region src/provide-blok.ts
90
- var V = Symbol("BLOK_DEFAULT_CONFIG");
91
- function H(e) {
92
- m(V, e);
90
+ var H = Symbol("BLOK_DEFAULT_CONFIG");
91
+ function U(e) {
92
+ m(H, e);
93
93
  }
94
- function U() {
95
- return o(V, {});
94
+ function W() {
95
+ return o(H, {});
96
96
  }
97
- function W(e, t) {
97
+ function G(e, t) {
98
98
  if (Object.keys(e).length === 0) return t;
99
- let n = B({}, e);
99
+ let n = V({}, e);
100
100
  for (let e of Object.keys(t)) {
101
101
  let r = t[e];
102
102
  r !== void 0 && (n[e] = r);
103
103
  }
104
- return (e.tools !== void 0 || t.tools !== void 0) && (n.tools = B(B({}, e.tools), t.tools)), n;
104
+ return (e.tools !== void 0 || t.tools !== void 0) && (n.tools = V(V({}, e.tools), t.tools)), n;
105
105
  }
106
106
  //#endregion
107
107
  //#region src/block-portal-registry.ts
108
- var G = "__blokPortalRegistry", K = () => {
108
+ var K = "__blokPortalRegistry", le = () => {
109
109
  let e = h(/* @__PURE__ */ new Map());
110
110
  return {
111
111
  entries: e,
@@ -122,13 +122,13 @@ var G = "__blokPortalRegistry", K = () => {
122
122
  }
123
123
  };
124
124
  }, q = /* @__PURE__ */ new WeakMap();
125
- function ce(e, t) {
125
+ function ue(e, t) {
126
126
  q.set(e, t);
127
127
  }
128
- function le(e) {
128
+ function de(e) {
129
129
  return q.get(e);
130
130
  }
131
- function ue(e) {
131
+ function fe(e) {
132
132
  q.delete(e);
133
133
  }
134
134
  //#endregion
@@ -140,7 +140,7 @@ var J = (e) => ({
140
140
  onSubmit: e.onSubmit !== void 0,
141
141
  onBeforeRender: e.onBeforeRender !== void 0,
142
142
  onAfterRender: e.onAfterRender !== void 0
143
- }), de = (e) => `[Blok] \`data\` is ignored while collaboration is on: the document lives on the sync service and is shared with everyone editing it, so replacing it from this editor would overwrite their work. To replace the whole document, call POST /sync/${e == null ? "{doc}" : e}/reset on your server — it reloads the document from your own document endpoint and every open editor picks it up. To change part of it, use the blocks API (insert/update/delete).`, fe = (e, t) => {
143
+ }), pe = (e) => `[Blok] \`data\` is ignored while collaboration is on: the document lives on the sync service and is shared with everyone editing it, so replacing it from this editor would overwrite their work. To replace the whole document, call POST /sync/${e == null ? "{doc}" : e}/reset on your server — it reloads the document from your own document endpoint and every open editor picks it up. To change part of it, use the blocks API (insert/update/delete).`, me = (e, t) => {
144
144
  if (typeof e != "object" || !e) return e;
145
145
  let n = {};
146
146
  for (let [i, a] of Object.entries(e)) {
@@ -150,19 +150,20 @@ var J = (e) => ({
150
150
  n[i] = a;
151
151
  continue;
152
152
  }
153
- let o = typeof a == "function" ? { class: a } : B({}, a);
154
- o.config = B(B({}, (r = o.config) == null ? {} : r), {}, { [G]: t }), n[i] = o;
153
+ let o = typeof a == "function" ? { class: a } : V({}, a);
154
+ o.config = V(V({}, (r = o.config) == null ? {} : r), {}, { [K]: t }), n[i] = o;
155
155
  }
156
156
  return n;
157
157
  };
158
158
  function Y(e, t) {
159
- let n = _(null), r = o(V, {}), i = () => W(r, y(e)), a = {
159
+ let n = _(null), r = o(H, {}), i = () => G(r, y(e)), a = {
160
160
  current: null,
161
161
  holder: null,
162
162
  lastRenderedData: i().data,
163
+ pendingData: void 0,
163
164
  seededEditor: null,
164
165
  renderChain: Promise.resolve(),
165
- collaborationWarned: !1,
166
+ collaborationWarnedFor: null,
166
167
  constructedCollaboration: void 0,
167
168
  appliedHandlerPresence: {
168
169
  onChange: !1,
@@ -172,14 +173,14 @@ function Y(e, t) {
172
173
  onBeforeRender: !1,
173
174
  onAfterRender: !1
174
175
  }
175
- }, s = {
176
+ }, s = ne(), c = {
176
177
  onChange: (...e) => {
177
178
  var t, n;
178
179
  (t = (n = i()).onChange) == null || t.call(n, ...e);
179
180
  },
180
181
  onSave: (...e) => {
181
182
  var t, n;
182
- a.lastRenderedData = e[0], (t = (n = i()).onSave) == null || t.call(n, ...e);
183
+ a.lastRenderedData = e[0], s.record(e[0]), (t = (n = i()).onSave) == null || t.call(n, ...e);
183
184
  },
184
185
  onEnter: (...e) => {
185
186
  var t, n;
@@ -197,37 +198,37 @@ function Y(e, t) {
197
198
  var t, n;
198
199
  (t = (n = i()).onAfterRender) == null || t.call(n, ...e);
199
200
  }
200
- }, c = () => {
201
- let t = B({}, W(v(r), v(y(e))));
202
- return delete t.holder, t.data !== void 0 && (t.data = v(t.data)), t;
203
201
  }, u = () => {
202
+ let t = V({}, G(v(r), v(y(e))));
203
+ return delete t.holder, t.data !== void 0 && (t.data = v(t.data)), t;
204
+ }, f = () => {
204
205
  if (a.current !== null) {
205
- se(a.current), ue(a.current), ae(a.current);
206
+ F(a.current), fe(a.current), se(a.current);
206
207
  try {
207
208
  a.current.destroy();
208
209
  } catch (e) {}
209
210
  }
210
211
  a.current = null, a.holder = null, n.value = null;
211
- }, f = () => {
212
+ }, p = () => {
212
213
  let e = document.createElement("div");
213
214
  a.holder = e;
214
- let t = c(), r = K();
215
- t.tools !== void 0 && (t.tools = fe(t.tools, r));
215
+ let t = u(), r = le();
216
+ t.tools !== void 0 && (t.tools = me(t.tools, r));
216
217
  let o = J(i());
217
- t.onChange = o.onChange ? s.onChange : void 0, t.onSave = o.onSave ? s.onSave : void 0, t.onEnter = o.onEnter ? s.onEnter : void 0, t.onSubmit = o.onSubmit ? s.onSubmit : void 0, t.onBeforeRender = o.onBeforeRender ? s.onBeforeRender : void 0, t.onAfterRender = o.onAfterRender ? s.onAfterRender : void 0, a.appliedHandlerPresence = o;
218
- let l = new x(B(B({}, t), {}, { holder: e }));
219
- a.current = l, a.constructedCollaboration = t.collaboration, oe(l, e), ce(l, r), re(l, { markRendered: (e) => {
220
- a.lastRenderedData = e;
218
+ t.onChange = o.onChange ? c.onChange : void 0, t.onSave = o.onSave ? c.onSave : void 0, t.onEnter = o.onEnter ? c.onEnter : void 0, t.onSubmit = o.onSubmit ? c.onSubmit : void 0, t.onBeforeRender = o.onBeforeRender ? c.onBeforeRender : void 0, t.onAfterRender = o.onAfterRender ? c.onAfterRender : void 0, a.appliedHandlerPresence = o;
219
+ let l = new x(V(V({}, t), {}, { holder: e }));
220
+ a.current = l, a.constructedCollaboration = t.collaboration, ce(l, e), ue(l, r), ae(l, { markRendered: (e) => {
221
+ s.clear(), a.lastRenderedData = e;
221
222
  } }), l.isReady.then(() => {
222
223
  a.current === l && (n.value = l);
223
224
  }).catch(() => {
224
- a.current === l && u();
225
+ a.current === l && f();
225
226
  });
226
227
  };
227
228
  b([
228
229
  n,
229
- () => A(i().readOnly).enabled,
230
- () => A(i().readOnly).hideControls,
230
+ () => j(i().readOnly).enabled,
231
+ () => j(i().readOnly).hideControls,
231
232
  () => typeof i().readOnly == "object"
232
233
  ], ([e, t, n, r]) => {
233
234
  e && (r ? e.readOnly.set(t, { hideControls: n }) : e.readOnly.set(t));
@@ -242,34 +243,35 @@ function Y(e, t) {
242
243
  }, { immediate: !0 }), b([n, () => i().placeholder], ([e, t]) => {
243
244
  e && t !== void 0 && e.placeholder.set(t);
244
245
  }, { immediate: !0 });
245
- let p = { value: void 0 };
246
+ let m = { value: void 0 };
246
247
  b([n, () => {
247
248
  var e;
248
249
  return (e = i().style) == null ? void 0 : e.tokens;
249
250
  }], ([e, t]) => {
250
- !e || t === void 0 || E(t, p.value) || (p.value = B({}, t), e.tokens.set(t));
251
+ e && t !== void 0 && !D(t, m.value) && (m.value = V({}, t), e.tokens.set(t));
251
252
  }, {
252
253
  immediate: !0,
253
254
  deep: !0
254
255
  });
255
- let m = { value: i().i18n };
256
+ let h = { value: i().i18n };
256
257
  b([n, () => i().i18n], ([e, t]) => {
257
- if (!e || t === void 0 || E(t, m.value)) return;
258
- m.value = B({}, t);
259
- let { locale: n, messages: r, direction: i } = t;
260
- e.i18n.update(B(B(B({}, n === void 0 ? {} : { locale: n }), r === void 0 ? {} : { messages: r }), i === void 0 ? {} : { direction: i }));
258
+ let n = h.value;
259
+ if (!e || t === void 0 && (n == null ? void 0 : n.direction) === void 0 || D(t, n)) return;
260
+ h.value = t === void 0 ? void 0 : V({}, t);
261
+ let { locale: r, messages: i, direction: a } = t == null ? {} : t, o = a == null ? (n == null ? void 0 : n.direction) === void 0 ? void 0 : null : a;
262
+ e.i18n.update(V(V(V({}, r === void 0 ? {} : { locale: r }), i === void 0 ? {} : { messages: i }), o === void 0 ? {} : { direction: o }));
261
263
  }, {
262
264
  immediate: !0,
263
265
  deep: !0
264
266
  });
265
- let h = {
267
+ let g = {
266
268
  editor: null,
267
269
  value: void 0
268
270
  };
269
271
  return b([n, () => i().inlineToolbar], ([e, t]) => {
270
- if (!e || t === void 0 || h.editor === e && E(t, h.value)) return;
272
+ if (!e || t === void 0 || g.editor === e && D(t, g.value)) return;
271
273
  let n = Array.isArray(t) ? [...t] : t;
272
- h.editor = e, h.value = n, e.tools.setInlineToolbar(n);
274
+ g.editor = e, g.value = n, e.tools.setInlineToolbar(n);
273
275
  }, {
274
276
  immediate: !0,
275
277
  deep: !0
@@ -277,44 +279,48 @@ function Y(e, t) {
277
279
  e && t && e.focus();
278
280
  }, { immediate: !0 }), b([n, () => JSON.stringify(J(i()))], ([e]) => {
279
281
  if (!e) return;
280
- let t = J(i()), n = a.appliedHandlerPresence, r = {}, o = { value: !1 }, c = (e, r) => {
281
- t[e] !== n[e] && (n[e] = t[e], o.value = !0, r(t[e] ? s[e] : void 0));
282
+ let t = J(i()), n = a.appliedHandlerPresence, r = {}, o = { value: !1 }, s = (e, r) => {
283
+ t[e] !== n[e] && (n[e] = t[e], o.value = !0, r(t[e] ? c[e] : void 0));
282
284
  };
283
- c("onChange", (e) => {
285
+ s("onChange", (e) => {
284
286
  r.onChange = e;
285
- }), c("onSave", (e) => {
287
+ }), s("onSave", (e) => {
286
288
  r.onSave = e;
287
- }), c("onEnter", (e) => {
289
+ }), s("onEnter", (e) => {
288
290
  r.onEnter = e;
289
- }), c("onSubmit", (e) => {
291
+ }), s("onSubmit", (e) => {
290
292
  r.onSubmit = e;
291
- }), c("onBeforeRender", (e) => {
293
+ }), s("onBeforeRender", (e) => {
292
294
  r.onBeforeRender = e;
293
- }), c("onAfterRender", (e) => {
295
+ }), s("onAfterRender", (e) => {
294
296
  r.onAfterRender = e;
295
297
  }), o.value && e.handlers.set(r);
296
298
  }, { immediate: !0 }), b([n, () => i().data], ([e, t]) => {
297
299
  if (!e || t === void 0) return;
298
300
  if (a.seededEditor !== e) {
299
- a.seededEditor = e, a.lastRenderedData = t;
301
+ a.seededEditor = e, a.lastRenderedData = t, a.pendingData = void 0, s.clear();
300
302
  return;
301
303
  }
302
- let n = a.lastRenderedData;
303
- if (n !== void 0 && D(t, n)) return;
304
- let r = a.constructedCollaboration;
305
- if (r !== void 0) {
306
- a.collaborationWarned || (a.collaborationWarned = !0, console.warn(de(r.doc)));
304
+ let n = a.lastRenderedData, r = a.pendingData;
305
+ if (n !== void 0 && O(t, n) || r !== void 0 && O(t, r) || s.matches(t)) return;
306
+ let i = a.constructedCollaboration;
307
+ if (i !== void 0) {
308
+ a.collaborationWarnedFor !== e && (a.collaborationWarnedFor = e, console.warn(pe(i.doc)));
307
309
  return;
308
310
  }
309
- a.lastRenderedData = t, a.renderChain = a.renderChain.catch(() => void 0).then(() => e.render(j(v(t))));
311
+ s.clear(), a.pendingData = t, a.renderChain = a.renderChain.then(() => e.render(re(v(t)))).then(() => {
312
+ a.lastRenderedData = t;
313
+ }, () => void 0).then(() => {
314
+ a.pendingData === t && (a.pendingData = void 0);
315
+ });
310
316
  }, { immediate: !0 }), t !== void 0 && b(() => y(t), () => {
311
- u(), f();
312
- }), d(f), l(u), n;
317
+ f(), p();
318
+ }), d(p), l(f), n;
313
319
  }
314
320
  //#endregion
315
321
  //#region src/useBlocks.ts
316
322
  var X = "block changed";
317
- function pe(e, t = {}) {
323
+ function he(e, t = {}) {
318
324
  let n = _(0), r = () => {
319
325
  let t = y(e);
320
326
  return t === null ? null : v(t);
@@ -334,9 +340,9 @@ function pe(e, t = {}) {
334
340
  let r = (r) => {
335
341
  var i;
336
342
  let a = (i = y(t.within)) == null ? null : i;
337
- a !== null && !ee(e, r, a) || (n.value += 1);
343
+ (a === null || E(e, r, a)) && (n.value += 1);
338
344
  };
339
- e.on(X, r), o.editor = e, o.handler = r, a.value = te(e, i);
345
+ e.on(X, r), o.editor = e, o.handler = r, a.value = ee(e, i);
340
346
  }, { immediate: !0 }), f(s), {
341
347
  getById: (e) => a.value.getById(e),
342
348
  getChildren: (e) => a.value.getChildren(e),
@@ -352,7 +358,7 @@ function pe(e, t = {}) {
352
358
  update: (e, t, n) => a.value.update(e, t, n),
353
359
  convert: (e, t, n, r) => a.value.convert(e, t, n, r),
354
360
  transact: (e) => a.value.transact(e),
355
- transactWithoutCapture: (e) => a.value.transactWithoutCapture(e),
361
+ transactWithoutCapture: (e, t) => a.value.transactWithoutCapture(e, t),
356
362
  getBlocksCount: () => a.value.getBlocksCount(),
357
363
  getCurrentBlockIndex: () => a.value.getCurrentBlockIndex(),
358
364
  getBlockByIndex: (e) => a.value.getBlockByIndex(e),
@@ -371,7 +377,7 @@ function pe(e, t = {}) {
371
377
  }
372
378
  //#endregion
373
379
  //#region src/useBlokReady.ts
374
- function me(e = {}) {
380
+ function ge(e = {}) {
375
381
  let { within: t, settleOn: n } = e, r = _(!1), i = () => {
376
382
  var e;
377
383
  let i = t === void 0 || (e = y(t)) == null ? null : e;
@@ -384,7 +390,7 @@ function me(e = {}) {
384
390
  }
385
391
  //#endregion
386
392
  //#region src/BlockPortalHost.ts
387
- var he = r({
393
+ var _e = r({
388
394
  name: "BlockErrorBoundary",
389
395
  setup(e, { slots: t }) {
390
396
  return u(() => !1), () => {
@@ -392,7 +398,7 @@ var he = r({
392
398
  return (e = t.default) == null ? void 0 : e.call(t);
393
399
  };
394
400
  }
395
- }), ge = r({
401
+ }), ve = r({
396
402
  name: "BlockPortalHost",
397
403
  props: { registry: {
398
404
  type: Object,
@@ -402,15 +408,15 @@ var he = r({
402
408
  return () => a(e, Array.from(n.registry.entries.entries()).map(([e, n]) => a(t, {
403
409
  key: e,
404
410
  to: n.hostEl
405
- }, [a(he, null, { default: () => a(n.component, n.props) })])));
411
+ }, [a(_e, null, { default: () => a(n.component, n.props) })])));
406
412
  }
407
- }), Z = Symbol("BLOK_EDITOR_INSTANCE"), _e = _(null);
408
- function Q() {
409
- return o(Z, _e);
413
+ }), Z = Symbol("BLOK_EDITOR_INSTANCE"), ye = _(null);
414
+ function be() {
415
+ return o(Z, ye);
410
416
  }
411
417
  //#endregion
412
418
  //#region src/BlokContent.ts
413
- var $ = r({
419
+ var Q = r({
414
420
  name: "BlokContent",
415
421
  props: { editor: {
416
422
  type: Object,
@@ -434,11 +440,17 @@ var $ = r({
434
440
  }), l(() => {
435
441
  i(e.editor);
436
442
  }), () => {
437
- let n = e.editor, r = n === null ? void 0 : le(v(n));
438
- return a("div", { ref: t }, r === void 0 ? [] : [a(ge, { registry: r })]);
443
+ let n = e.editor, r = n === null ? void 0 : de(v(n));
444
+ return a("div", { ref: t }, r === void 0 ? [] : [a(ve, { registry: r })]);
439
445
  };
440
446
  }
441
- }), ve = /* @__PURE__ */ "autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.toolbarPosition.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.inlineEmoji.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter.onSubmit.onError.migrations.uploader.server.ticket.persistence.collaboration.captureClicksBelowEditor".split("."), ye = r({
447
+ }), xe = /* @__PURE__ */ "autofocus.defaultBlock.dataModel.placeholder.sanitizer.hideToolbar.toolbarPosition.maxHistoryLength.historyDebounceTime.newGroupDelay.globalUndoRedo.tools.data.minHeight.loader.logLevel.readOnly.i18n.link.linkPaste.inlineToolbar.inlineEmoji.find.tunes.style.theme.scrollToBlock.user.resolveUser.notifierPosition.notifier.width.onBeforeRender.onBeforePaste.onEnter.onSubmit.onError.onImageFailure.migrations.uploader.media.server.ticket.persistence.collaboration.documentId.tabSync.captureClicksBelowEditor".split("."), Se = (e, t, n) => {
448
+ let r = t.flatMap((t) => {
449
+ var n;
450
+ return (n = e == null ? void 0 : e[t]) == null ? [] : n;
451
+ });
452
+ for (let e of r) typeof e == "function" && e(n);
453
+ }, Ce = r({
442
454
  name: "BlokEditor",
443
455
  inheritAttrs: !1,
444
456
  props: {
@@ -498,6 +510,10 @@ var $ = r({
498
510
  type: Number,
499
511
  default: void 0
500
512
  },
513
+ loader: {
514
+ type: [Boolean, Object],
515
+ default: void 0
516
+ },
501
517
  logLevel: {
502
518
  type: String,
503
519
  default: void 0
@@ -526,6 +542,10 @@ var $ = r({
526
542
  type: Boolean,
527
543
  default: void 0
528
544
  },
545
+ find: {
546
+ type: [Boolean, Object],
547
+ default: void 0
548
+ },
529
549
  tunes: {
530
550
  type: Array,
531
551
  default: void 0
@@ -582,6 +602,10 @@ var $ = r({
582
602
  type: Function,
583
603
  default: void 0
584
604
  },
605
+ onImageFailure: {
606
+ type: Function,
607
+ default: void 0
608
+ },
585
609
  migrations: {
586
610
  type: Object,
587
611
  default: void 0
@@ -590,6 +614,10 @@ var $ = r({
590
614
  type: Object,
591
615
  default: void 0
592
616
  },
617
+ media: {
618
+ type: Object,
619
+ default: void 0
620
+ },
593
621
  server: {
594
622
  type: String,
595
623
  default: void 0
@@ -606,6 +634,14 @@ var $ = r({
606
634
  type: Object,
607
635
  default: void 0
608
636
  },
637
+ documentId: {
638
+ type: String,
639
+ default: void 0
640
+ },
641
+ tabSync: {
642
+ type: [Boolean, Object],
643
+ default: void 0
644
+ },
609
645
  captureClicksBelowEditor: {
610
646
  type: Boolean,
611
647
  default: void 0
@@ -632,7 +668,7 @@ var $ = r({
632
668
  });
633
669
  let u = (e) => l.value.split("|").includes(e), d = () => {
634
670
  let n = {};
635
- for (let t of ve) {
671
+ for (let t of xe) {
636
672
  let r = e[t];
637
673
  r !== void 0 && (n[t] = r);
638
674
  }
@@ -642,6 +678,10 @@ var $ = r({
642
678
  event: n
643
679
  });
644
680
  }), (u("onSave") || u("onUpdate:data")) && (n.onSave = (e) => {
681
+ if ((s == null ? void 0 : s.isUnmounted) === !0) {
682
+ Se(s.vnode.props, ["onUpdate:data", "onSave"], e);
683
+ return;
684
+ }
645
685
  t("update:data", e), t("save", e);
646
686
  }), u("onAfterRender") && (n.onAfterRender = (e) => {
647
687
  t("after-render", e);
@@ -673,6 +713,10 @@ var $ = r({
673
713
  var e;
674
714
  return (e = f.value) == null ? void 0 : e.save();
675
715
  },
716
+ confirmLeave: () => {
717
+ var e, t;
718
+ return (e = (t = f.value) == null ? void 0 : t.confirmLeave()) == null ? Promise.resolve(!0) : e;
719
+ },
676
720
  focus: (e) => {
677
721
  var t;
678
722
  (t = f.value) == null || t.focus(e);
@@ -681,28 +725,28 @@ var $ = r({
681
725
  let t = f.value;
682
726
  if (t !== null) return t.render(e).then(() => {
683
727
  var n;
684
- (n = ie(t)) == null || n.markRendered(e);
728
+ (n = oe(t)) == null || n.markRendered(e);
685
729
  });
686
730
  }
687
- }), () => a($, B({ editor: f.value }, o));
731
+ }), () => a(Q, V({ editor: f.value }, o));
688
732
  }
689
- }), be = [
733
+ }), $ = [
690
734
  "toolbox",
691
735
  "isReadOnlySupported",
692
736
  "__isBlokVueBlock"
693
- ], xe = /* @__PURE__ */ new Set([
737
+ ], we = /* @__PURE__ */ new Set([
694
738
  void 0,
695
739
  "user",
696
740
  "api",
697
741
  "convert"
698
- ]), Se = (e, t, n) => {
742
+ ]), Te = (e, t, n) => {
699
743
  var r;
700
744
  e == null || (r = e.events) == null || r.emit(S, {
701
745
  blockId: t,
702
746
  childIds: n.map((e) => e.id)
703
747
  });
704
748
  };
705
- function Ce(e) {
749
+ function Ee(e) {
706
750
  var t, n;
707
751
  let i = () => r({
708
752
  name: `VueBlock(${e.type})`,
@@ -742,21 +786,21 @@ function Ce(e) {
742
786
  origin: this.origin,
743
787
  api: this.api
744
788
  };
745
- if ((t = e.onMounted) == null || t.call(e, this.blockApi, n), xe.has(this.origin)) {
789
+ if ((t = e.onMounted) == null || t.call(e, this.blockApi, n), we.has(this.origin)) {
746
790
  var r;
747
791
  (r = e.onCreated) == null || r.call(e, this.blockApi, n);
748
792
  }
749
793
  }, this.commit = (t) => {
750
- let n = O(e.propSchema, B(B({}, this.mirror), t));
751
- E(n, this.mirror) || (this.mirror = n, this.lastRendered = n, this.dataRef.value = n, this.flushDispatch());
794
+ let n = k(e.propSchema, V(V({}, this.mirror), t));
795
+ D(n, this.mirror) || (this.mirror = n, this.lastRendered = n, this.dataRef.value = n, this.flushDispatch());
752
796
  }, this.blockApi = t.block;
753
797
  let c = (n = t.config) == null ? {} : n;
754
- this.registry = c[G], this.api = t.api;
798
+ this.registry = c[K], this.api = t.api;
755
799
  let l = t.api;
756
800
  this.pointerDrag = () => {
757
801
  var e;
758
802
  return (l == null || (e = l.blocks) == null ? void 0 : e.isPointerDragActive) === !0;
759
- }, this.mirror = O(e.propSchema, v((o = t.data) == null ? {} : o)), this.lastRendered = this.mirror, this.dataRef = _(this.mirror), this.readOnlyRef = _(t.readOnly), this.origin = (s = t.origin) == null ? "api" : s;
803
+ }, this.mirror = k(e.propSchema, v((o = t.data) == null ? {} : o)), this.lastRendered = this.mirror, this.dataRef = _(this.mirror), this.readOnlyRef = _(t.readOnly), this.origin = (s = t.origin) == null ? "api" : s;
760
804
  let u = this.blockApi, f = this.api;
761
805
  this.childrenComponent = r({
762
806
  name: `VueBlockChildren(${e.type})`,
@@ -771,13 +815,13 @@ function Ce(e) {
771
815
  }
772
816
  },
773
817
  setup(e) {
774
- let t = g(null), n = ne(), r = () => {
818
+ let t = g(null), n = te(), r = () => {
775
819
  if (t.value === null) return;
776
820
  let r = u.getChildren();
777
- k(t.value, r), T(n, r, {
821
+ A(t.value, ie(r, (e) => f.blocks.getChildren(e))), T(n, r, {
778
822
  childAttributes: e.childAttributes,
779
823
  childContentAttributes: e.childContentAttributes
780
- }), Se(f, u.id, r);
824
+ }), Te(f, u.id, r);
781
825
  };
782
826
  return d(r), p(r), () => a("div", {
783
827
  ref: t,
@@ -816,9 +860,8 @@ function Ce(e) {
816
860
  return this.mirror;
817
861
  }
818
862
  async setData(t) {
819
- var n = this;
820
- let r = O(e.propSchema, v(t == null ? {} : t));
821
- return E(r, n.lastRendered) ? !0 : (n.mirror = r, n.lastRendered = r, n.dataRef.value = r, await c(), !0);
863
+ let n = k(e.propSchema, v(t == null ? {} : t));
864
+ return D(n, this.lastRendered) ? !0 : (this.mirror = n, this.lastRendered = n, this.dataRef.value = n, await c(), !0);
822
865
  }
823
866
  setReadOnly(e) {
824
867
  this.readOnlyRef.value = e;
@@ -830,6 +873,10 @@ function Ce(e) {
830
873
  let r = this.hostEl;
831
874
  if (r !== null && e.getToolbarAnchorElement !== void 0) return (t = e.getToolbarAnchorElement(r, this.blockApi)) == null ? void 0 : t;
832
875
  }
876
+ onNavigationEnter(t) {
877
+ var n;
878
+ return ((n = e.onNavigationEnter) == null ? void 0 : n.call(e, t, this.blockApi)) === !0;
879
+ }
833
880
  moved() {
834
881
  var t;
835
882
  (t = e.onMoved) == null || t.call(e, this.blockApi);
@@ -859,7 +906,7 @@ function Ce(e) {
859
906
  requestAnimationFrame(e);
860
907
  }
861
908
  }, t.__isBlokVueBlock = !0, t);
862
- for (let [t, r] of Object.entries((n = e.statics) == null ? {} : n)) be.includes(t) || Object.defineProperty(o, t, {
909
+ for (let [t, r] of Object.entries((n = e.statics) == null ? {} : n)) $.includes(t) || Object.defineProperty(o, t, {
863
910
  value: r,
864
911
  writable: !0,
865
912
  enumerable: !0,
@@ -868,4 +915,4 @@ function Ce(e) {
868
915
  return o;
869
916
  }
870
917
  //#endregion
871
- export { V as BLOK_DEFAULT_CONFIG, Z as BLOK_EDITOR_INSTANCE, $ as BlokContent, ye as BlokEditor, Ce as createVueBlock, H as provideBlok, pe as useBlocks, Y as useBlok, U as useBlokDefaults, Q as useBlokInstance, me as useBlokReady };
918
+ export { H as BLOK_DEFAULT_CONFIG, Z as BLOK_EDITOR_INSTANCE, Q as BlokContent, Ce as BlokEditor, Ee as createVueBlock, U as provideBlok, he as useBlocks, Y as useBlok, W as useBlokDefaults, be as useBlokInstance, ge as useBlokReady };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bloklabs/vue",
3
- "version": "1.15.2",
3
+ "version": "1.16.1",
4
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",
@@ -54,7 +54,7 @@
54
54
  "build": "yarn run -T vite build --mode production"
55
55
  },
56
56
  "peerDependencies": {
57
- "@bloklabs/core": "^1.15.2",
57
+ "@bloklabs/core": "^1.16.1",
58
58
  "vue": "^3.5.0"
59
59
  }
60
60
  }
package/src/BlokEditor.ts CHANGED
@@ -14,6 +14,23 @@ import type {
14
14
  } from '@/types';
15
15
  import type { UseBlokConfig } from './types';
16
16
 
17
+ /**
18
+ * Calls emit-mapped listeners read from a vnode's props. Vue stores one as a
19
+ * function, or as an array when several are bound to the same event.
20
+ * @param vnodeProps - the component vnode's props
21
+ * @param keys - listener keys, e.g. `onSave`
22
+ * @param data - the payload
23
+ */
24
+ const callVnodeListeners = (vnodeProps: Record<string, unknown> | null, keys: string[], data: OutputData): void => {
25
+ const listeners: unknown[] = keys.flatMap((key) => vnodeProps?.[key] ?? []);
26
+
27
+ for (const listener of listeners) {
28
+ if (typeof listener === 'function') {
29
+ (listener as (payload: OutputData) => void)(data);
30
+ }
31
+ }
32
+ };
33
+
17
34
  /**
18
35
  * The blessed all-in-one component for embedding Blok in Vue. Wires `useBlok`
19
36
  * and `BlokContent`, maps Vue emits onto the core config callbacks (gated on
@@ -46,6 +63,7 @@ export const BlokEditor = defineComponent({
46
63
  tools: { type: Object as PropType<BlokConfig['tools']>, default: undefined },
47
64
  data: { type: Object as PropType<OutputData>, default: undefined },
48
65
  minHeight: { type: Number, default: undefined },
66
+ loader: { type: [Boolean, Object] as PropType<BlokConfig['loader']>, default: undefined },
49
67
  logLevel: { type: String as PropType<BlokConfig['logLevel']>, default: undefined },
50
68
  // [Boolean, Object]: the object form ({ hideControls }) must not be dropped
51
69
  // or dev-warned — it always means read-only enabled (reactive contract).
@@ -55,6 +73,7 @@ export const BlokEditor = defineComponent({
55
73
  linkPaste: { type: Object as PropType<BlokConfig['linkPaste']>, default: undefined },
56
74
  inlineToolbar: { type: [Array, Boolean] as PropType<string[] | boolean>, default: undefined },
57
75
  inlineEmoji: { type: Boolean as PropType<boolean | undefined>, default: undefined },
76
+ find: { type: [Boolean, Object] as PropType<BlokConfig['find']>, default: undefined },
58
77
  tunes: { type: Array as PropType<string[]>, default: undefined },
59
78
  style: { type: Object as PropType<BlokConfig['style']>, default: undefined },
60
79
  theme: { type: String as PropType<ThemeMode>, default: undefined },
@@ -74,10 +93,13 @@ export const BlokEditor = defineComponent({
74
93
  onSubmit: { type: Function as PropType<BlokConfig['onSubmit']>, default: undefined },
75
94
  // Fire-and-forget error channel — a plain declared prop copied into config.
76
95
  onError: { type: Function as PropType<BlokConfig['onError']>, default: undefined },
96
+ onImageFailure: { type: Function as PropType<BlokConfig['onImageFailure']>, default: undefined },
77
97
  /** Host-supplied per-type block migrations applied at load. */
78
98
  migrations: { type: Object as PropType<BlokConfig['migrations']>, default: undefined },
79
99
  /** Editor-level uploader, routed by asset kind (images, video, audio, files). */
80
100
  uploader: { type: Object as PropType<BlokConfig['uploader']>, default: undefined },
101
+ /** Convert uploaded photos and videos into several formats, rendered best-first. */
102
+ media: { type: Object as PropType<BlokConfig['media']>, default: undefined },
81
103
  /** Base URL of a service speaking Blok's upload and unfurl contracts. */
82
104
  server: { type: String as PropType<BlokConfig['server']>, default: undefined },
83
105
  /** Endpoint in your app that mints a short-lived access pass for the current user. */
@@ -86,6 +108,10 @@ export const BlokEditor = defineComponent({
86
108
  persistence: { type: Object as PropType<BlokConfig['persistence']>, default: undefined },
87
109
  /** Real-time multiplayer against the server's sync service. Mutually exclusive with persistence. */
88
110
  collaboration: { type: Object as PropType<BlokConfig['collaboration']>, default: undefined },
111
+ /** Your app's id for this document; tabs showing the same id stay in sync. Mount-fixed. */
112
+ documentId: { type: String as PropType<BlokConfig['documentId']>, default: undefined },
113
+ /** Live sync between tabs of this browser. On by default. */
114
+ tabSync: { type: [Boolean, Object] as PropType<BlokConfig['tabSync']>, default: undefined },
89
115
  /** Opt-in: clicks on the host page below the editor append a block. */
90
116
  captureClicksBelowEditor: { type: Boolean as PropType<boolean | undefined>, default: undefined },
91
117
  /** Changing this prop's identity destroys and recreates the editor. */
@@ -181,6 +207,14 @@ export const BlokEditor = defineComponent({
181
207
  // v-model:data binding or an explicit @save listener consumes it.
182
208
  if (hasListener('onSave') || hasListener('onUpdate:data')) {
183
209
  config.onSave = (data: OutputData): void => {
210
+ // Vue drops emits once unmounted, but destroy()'s final save lands
211
+ // after that, so call the listeners straight from the vnode.
212
+ if (instance?.isUnmounted === true) {
213
+ callVnodeListeners(instance.vnode.props, ['onUpdate:data', 'onSave'], data);
214
+
215
+ return;
216
+ }
217
+
184
218
  emit('update:data', data);
185
219
  emit('save', data);
186
220
  };
@@ -258,6 +292,7 @@ export const BlokEditor = defineComponent({
258
292
  expose({
259
293
  instance: computed(() => editor.value),
260
294
  save: (): ReturnType<NonNullable<typeof editor.value>['save']> | undefined => editor.value?.save(),
295
+ confirmLeave: (): Promise<boolean> => editor.value?.confirmLeave() ?? Promise.resolve(true),
261
296
  focus: (atEnd?: boolean): void => {
262
297
  editor.value?.focus(atEnd);
263
298
  },
@@ -28,6 +28,7 @@ export const BLOK_EDITOR_CONFIG_KEYS = [
28
28
  'tools',
29
29
  'data',
30
30
  'minHeight',
31
+ 'loader',
31
32
  'logLevel',
32
33
  'readOnly',
33
34
  'i18n',
@@ -35,6 +36,7 @@ export const BLOK_EDITOR_CONFIG_KEYS = [
35
36
  'linkPaste',
36
37
  'inlineToolbar',
37
38
  'inlineEmoji',
39
+ 'find',
38
40
  'tunes',
39
41
  'style',
40
42
  'theme',
@@ -49,12 +51,16 @@ export const BLOK_EDITOR_CONFIG_KEYS = [
49
51
  'onEnter',
50
52
  'onSubmit',
51
53
  'onError',
54
+ 'onImageFailure',
52
55
  'migrations',
53
56
  'uploader',
57
+ 'media',
54
58
  'server',
55
59
  'ticket',
56
60
  'persistence',
57
61
  'collaboration',
62
+ 'documentId',
63
+ 'tabSync',
58
64
  'captureClicksBelowEditor',
59
65
  ] as const satisfies readonly (keyof UseBlokConfig)[];
60
66
 
@@ -74,5 +80,3 @@ export type EmitMappedConfigKey = 'onReady' | 'onChange' | 'onSave' | 'onAfterRe
74
80
  */
75
81
  type _UncoveredConfigKey = Exclude<keyof UseBlokConfig, BlokEditorConfigKey | EmitMappedConfigKey>;
76
82
  const _uncovered: _UncoveredConfigKey extends never ? true : never = true;
77
-
78
- void _uncovered;
@@ -31,6 +31,7 @@ import {
31
31
  DATA_ATTR,
32
32
  deepEqual,
33
33
  mountChildBlocks,
34
+ withSlotlessDescendants,
34
35
  } from '@bloklabs/core/adapters';
35
36
  import { fillDefaults, type PropSchema } from '@bloklabs/core/adapters';
36
37
 
@@ -248,6 +249,15 @@ export interface CreateVueBlockSpec<Data = BlockToolData> {
248
249
  * @param block - this block's per-block API
249
250
  */
250
251
  getToolbarAnchorElement?: (host: HTMLElement, block: BlockAPI) => HTMLElement | null | undefined;
252
+ /**
253
+ * Enter (or Cmd/Ctrl+Enter) on this block while it is the keyboard
254
+ * navigation target — core's `onNavigationEnter` hook. Return true when the
255
+ * block handled it (e.g. opened a link); omit it, or return false, to let
256
+ * core put the caret in the block.
257
+ * @param event - the Enter keydown
258
+ * @param block - this block's per-block API
259
+ */
260
+ onNavigationEnter?: (event: KeyboardEvent, block: BlockAPI) => boolean;
251
261
  /** Optional lifecycle callbacks mapped from Blok's block hooks. */
252
262
  onRendered?: (block: BlockAPI) => void;
253
263
  /**
@@ -328,6 +338,7 @@ export function createVueBlock<Data = BlockToolData>(
328
338
  setData(newData: BlockToolData): Promise<boolean>;
329
339
  setReadOnly(state: boolean): void;
330
340
  getToolbarAnchorElement(): HTMLElement | undefined;
341
+ onNavigationEnter(event: KeyboardEvent): boolean;
331
342
  rendered(): void;
332
343
  moved(): void;
333
344
  removed(): void;
@@ -483,7 +494,9 @@ export function createVueBlock<Data = BlockToolData>(
483
494
 
484
495
  const children = blockApi.getChildren();
485
496
 
486
- mountChildBlocks(slot.value, children);
497
+ // A slotless child's own children live in this slot too. Decoration
498
+ // and the mounted event stay per DIRECT child.
499
+ mountChildBlocks(slot.value, withSlotlessDescendants(children, id => api.blocks.getChildren(id)));
487
500
  applyChildDecoration(ledger, children, {
488
501
  childAttributes: props.childAttributes,
489
502
  childContentAttributes: props.childContentAttributes,
@@ -624,6 +637,14 @@ export function createVueBlock<Data = BlockToolData>(
624
637
  return spec.getToolbarAnchorElement(host, this.blockApi) ?? undefined;
625
638
  }
626
639
 
640
+ /**
641
+ * Core's navigation-mode Enter hook. Only a real `true` from the spec
642
+ * counts as handled.
643
+ */
644
+ public onNavigationEnter(event: KeyboardEvent): boolean {
645
+ return spec.onNavigationEnter?.(event, this.blockApi) === true;
646
+ }
647
+
627
648
  public moved(): void {
628
649
  // No remount: Blok relocates the host element; the teleport follows it.
629
650
  spec.onMoved?.(this.blockApi);
package/src/useBlocks.ts CHANGED
@@ -86,7 +86,7 @@ export function useBlocks(
86
86
  // The reactivity seam handed to the shared core: every read method calls it,
87
87
  // so a read inside a Vue effect tracks `version` and re-runs on mutation.
88
88
  const touch = (): void => {
89
- void version.value;
89
+ version.value;
90
90
  };
91
91
 
92
92
  // The API bound to the CURRENT editor. Rebuilt by the watch below when the
@@ -161,7 +161,7 @@ export function useBlocks(
161
161
  update: (id, data, tunes) => bound.value.update(id, data, tunes),
162
162
  convert: (id, newType, dataOverrides, options) => bound.value.convert(id, newType, dataOverrides, options),
163
163
  transact: (fn) => bound.value.transact(fn),
164
- transactWithoutCapture: (fn) => bound.value.transactWithoutCapture(fn),
164
+ transactWithoutCapture: (fn, options) => bound.value.transactWithoutCapture(fn, options),
165
165
  getBlocksCount: () => bound.value.getBlocksCount(),
166
166
  getCurrentBlockIndex: () => bound.value.getCurrentBlockIndex(),
167
167
  getBlockByIndex: (index) => bound.value.getBlockByIndex(index),
package/src/useBlok.ts CHANGED
@@ -12,7 +12,13 @@ import {
12
12
  import { Blok as BlokRuntime } from '@bloklabs/core';
13
13
  import { setContentBaseline, removeContentBaseline } from './content-baseline-map';
14
14
  import { setHolder, removeHolder } from './holder-map';
15
- import { deepEqual, equalsOutputData, normalizeReadOnlyConfig, toRenderableData } from '@bloklabs/core/adapters';
15
+ import {
16
+ createEmittedEchoWindow,
17
+ deepEqual,
18
+ equalsOutputData,
19
+ normalizeReadOnlyConfig,
20
+ toRenderableData,
21
+ } from '@bloklabs/core/adapters';
16
22
  import { BLOK_DEFAULT_CONFIG, mergeBlokDefaults } from './provide-blok';
17
23
  import {
18
24
  createBlockPortalRegistry,
@@ -137,9 +143,19 @@ export function useBlok(
137
143
  current: Blok | null;
138
144
  holder: HTMLDivElement | null;
139
145
  lastRenderedData: OutputData | LooseOutputData | null | undefined;
146
+ // Content of the render currently queued/in-flight — distinct from
147
+ // `lastRenderedData`, which is the last SUCCESSFULLY rendered content.
148
+ // Dedupes a re-queue of the same in-flight content without advancing the
149
+ // success baseline, so a failed render cannot strand the baseline on
150
+ // content the editor never showed.
151
+ pendingData: OutputData | LooseOutputData | null | undefined;
140
152
  seededEditor: Blok | null;
141
153
  renderChain: Promise<void>;
142
- collaborationWarned: boolean;
154
+ // Editor the single collaboration warning has already been emitted for.
155
+ // Keyed by the editor, not a boolean, so the editor a `recreateKey` bump
156
+ // creates warns on its own first ignored `data` change instead of
157
+ // inheriting the previous editor's "already warned" flag and going silent.
158
+ collaborationWarnedFor: Blok | null;
143
159
  // The `collaboration` the live editor was CONSTRUCTED with. The key is
144
160
  // mount-fixed, so dropping it from the config (`collaboration: on ? {...} :
145
161
  // undefined`) cannot turn a live session into a single-player editor —
@@ -152,9 +168,10 @@ export function useBlok(
152
168
  current: null,
153
169
  holder: null,
154
170
  lastRenderedData: mergedConfig().data,
171
+ pendingData: undefined,
155
172
  seededEditor: null,
156
173
  renderChain: Promise.resolve(),
157
- collaborationWarned: false,
174
+ collaborationWarnedFor: null,
158
175
  constructedCollaboration: undefined,
159
176
  appliedHandlerPresence: {
160
177
  onChange: false,
@@ -166,6 +183,15 @@ export function useBlok(
166
183
  },
167
184
  };
168
185
 
186
+ // Window of recently emitted `onSave` payloads. `state.lastRenderedData`
187
+ // remembers only the LAST one, but a host that persists on save and refetches
188
+ // can echo an EARLIER save back after a newer one already replaced the
189
+ // baseline (the user kept typing). That stale echo is still the editor's own
190
+ // output, and rendering it is a whole-document replace — it would drop every
191
+ // character typed between the two saves and hand the rewound document to the
192
+ // next save, making the loss permanent in the host's store.
193
+ const emittedEcho = createEmittedEchoWindow();
194
+
169
195
  /**
170
196
  * Stable wrappers for the live callback config. Each forwards to the LATEST
171
197
  * config through `mergedConfig()`, so callback identity never goes stale and
@@ -180,6 +206,7 @@ export function useBlok(
180
206
  // notifying the consumer, so a controlled `update:data -> data` echo
181
207
  // content-equals it and never re-renders.
182
208
  state.lastRenderedData = args[0];
209
+ emittedEcho.record(args[0]);
183
210
  mergedConfig().onSave?.(...args);
184
211
  },
185
212
  // Forward the return value: it is the "handled" signal the core acts on.
@@ -280,6 +307,10 @@ export function useBlok(
280
307
  // content while the host's state says otherwise.
281
308
  setContentBaseline(blok, {
282
309
  markRendered: (content): void => {
310
+ // Out-of-band content: what the editor emitted before describes a
311
+ // document it no longer shows, so a later `data` set back to one of
312
+ // those payloads must render instead of being dismissed as an echo.
313
+ emittedEcho.clear();
283
314
  state.lastRenderedData = content;
284
315
  },
285
316
  });
@@ -408,18 +439,22 @@ export function useBlok(
408
439
  watch(
409
440
  [editor, () => mergedConfig().i18n],
410
441
  ([ed, i18n]) => {
411
- if (!ed || i18n === undefined || deepEqual(i18n, appliedI18n.value)) {
442
+ const previous = appliedI18n.value;
443
+
444
+ if (!ed || (i18n === undefined && previous?.direction === undefined) || deepEqual(i18n, previous)) {
412
445
  return;
413
446
  }
414
447
 
415
- appliedI18n.value = { ...i18n };
448
+ appliedI18n.value = i18n === undefined ? undefined : { ...i18n };
416
449
 
417
- const { locale, messages, direction } = i18n;
450
+ const { locale, messages, direction } = i18n ?? {};
451
+ // A dropped direction must be cleared, or the editor keeps the old one.
452
+ const nextDirection = direction ?? (previous?.direction === undefined ? undefined : null);
418
453
 
419
454
  void ed.i18n.update({
420
455
  ...(locale === undefined ? {} : { locale }),
421
456
  ...(messages === undefined ? {} : { messages }),
422
- ...(direction === undefined ? {} : { direction }),
457
+ ...(nextDirection === undefined ? {} : { direction: nextDirection }),
423
458
  });
424
459
  },
425
460
  { immediate: true, deep: true }
@@ -539,19 +574,39 @@ export function useBlok(
539
574
  if (state.seededEditor !== ed) {
540
575
  state.seededEditor = ed;
541
576
  state.lastRenderedData = data;
577
+ // A render still pending on a PRIOR editor is moot for this fresh
578
+ // instance; clear it so its content can't dedupe a needed render here.
579
+ state.pendingData = undefined;
580
+ // Payloads emitted by a PRIOR editor are likewise moot for this one.
581
+ emittedEcho.clear();
542
582
 
543
583
  return;
544
584
  }
545
585
 
586
+ // Skipped when the editor already reflects this content (the last
587
+ // SUCCESSFUL render) OR a render of the same content is already
588
+ // queued/in-flight — re-rendering identical content would needlessly
589
+ // reset the caret.
590
+ //
546
591
  // Structural comparison (`equalsOutputData`, not a raw deep-equal): a host
547
592
  // that persists the editor's own document and hands back a stripped copy —
548
593
  // fresh `time`, dropped ids, no `lastEditedAt` stamp — is still echoing
549
- // content the editor already shows, and re-rendering it would reset the
550
- // caret for zero visual change. `undefined` means "nothing recorded yet",
551
- // which is NOT an empty document, so it must never match.
594
+ // content the editor already shows. `undefined` means "nothing recorded
595
+ // yet", which is NOT an empty document, so it must never match.
552
596
  const baseline = state.lastRenderedData;
597
+ const inFlight = state.pendingData;
598
+
599
+ if (
600
+ (baseline !== undefined && equalsOutputData(data, baseline)) ||
601
+ (inFlight !== undefined && equalsOutputData(data, inFlight))
602
+ ) {
603
+ return;
604
+ }
553
605
 
554
- if (baseline !== undefined && equalsOutputData(data, baseline)) {
606
+ // Skip stale echoes: content the editor itself emitted via `onSave`
607
+ // recently, arriving back reshaped (fresh envelope, stripped ids) and/or
608
+ // late — after a newer save already replaced the baseline above.
609
+ if (emittedEcho.matches(data)) {
555
610
  return;
556
611
  }
557
612
 
@@ -565,21 +620,48 @@ export function useBlok(
565
620
  const collaboration = state.constructedCollaboration;
566
621
 
567
622
  if (collaboration !== undefined) {
568
- if (!state.collaborationWarned) {
569
- state.collaborationWarned = true;
623
+ if (state.collaborationWarnedFor !== ed) {
624
+ state.collaborationWarnedFor = ed;
570
625
  console.warn(collaborationDataIgnoredMessage(collaboration.doc));
571
626
  }
572
627
 
573
628
  return;
574
629
  }
575
630
 
576
- state.lastRenderedData = data;
631
+ // Genuinely external content takes over: earlier emitted payloads are
632
+ // moot, and keeping them could wrongly no-op a later deliberate revert to
633
+ // one of them.
634
+ emittedEcho.clear();
635
+
636
+ // Mark the content in-flight, but DON'T advance the success baseline until
637
+ // the render resolves. A failed render leaves the editor on its last
638
+ // successful content, so the baseline must keep pointing there — otherwise
639
+ // a run of failures would strand it on a never-rendered payload and
640
+ // wrongly dedupe a later retry.
641
+ state.pendingData = data;
577
642
  // `data` may be null (a controlled "clear to empty"); render() throws on
578
643
  // null, so normalize null → { blocks: [] } at the boundary. toRaw(null)
579
644
  // stays null, so the helper still sees it.
645
+ // The rejection handler OWNS a failed render: without it the rejection
646
+ // sits in `renderChain` unhandled until the next `data` change attaches a
647
+ // handler, which the runtime reports as an unhandled rejection. Because
648
+ // the chain can no longer reject, no leading catch is needed to keep the
649
+ // next queued render running.
580
650
  state.renderChain = state.renderChain
581
- .catch(() => undefined)
582
- .then(() => ed.render(toRenderableData(toRaw(data))));
651
+ .then(() => ed.render(toRenderableData(toRaw(data))))
652
+ .then(
653
+ () => {
654
+ state.lastRenderedData = data;
655
+ },
656
+ () => undefined
657
+ )
658
+ .then(() => {
659
+ // Clear the in-flight marker once settled, unless a newer render has
660
+ // since claimed it (then that newer render owns the clear).
661
+ if (state.pendingData === data) {
662
+ state.pendingData = undefined;
663
+ }
664
+ });
583
665
  },
584
666
  { immediate: true }
585
667
  );
package/types/index.d.ts CHANGED
@@ -124,6 +124,8 @@ export interface BlokEditorExposed {
124
124
  instance: Blok | null;
125
125
  /** Serialize the current content (undefined until ready). */
126
126
  save(): Promise<OutputData> | undefined;
127
+ /** Ask before an in-app navigation (see `Blok.confirmLeave`). Resolves true until ready. */
128
+ confirmLeave(): Promise<boolean>;
127
129
  /** Move the caret into the editor. */
128
130
  focus(atEnd?: boolean): void;
129
131
  /**
@@ -383,8 +385,12 @@ export interface UseBlocksApi {
383
385
  * Run `fn` as one atomic operation NOT captured in the undo history — for
384
386
  * silent auto-repair a user's undo should never step through. Mutations inside
385
387
  * still emit reactively. Pre-ready it just runs `fn`.
388
+ *
389
+ * With `options`, the operations are data worked out from the `from` keys of
390
+ * block `derivedFrom` (a finished upload, for example): they join the undo
391
+ * entry that wrote those values, as in core.
386
392
  */
387
- transactWithoutCapture(fn: () => void): void;
393
+ transactWithoutCapture(fn: () => void, options?: { derivedFrom?: string; from?: readonly string[] }): void;
388
394
  /** The current block count. Reactive (re-reads on 'block changed'). Pre-ready: 0. */
389
395
  getBlocksCount(): number;
390
396
  /** The flat index of the block holding the caret, or -1 when none. Pre-ready: -1. */
@@ -674,6 +680,15 @@ export interface CreateVueBlockSpec<Data extends BlockToolData = BlockToolData>
674
680
  * call. Return `null`/`undefined` to keep core's default positioning.
675
681
  */
676
682
  getToolbarAnchorElement?: (host: HTMLElement, block: BlockAPI) => HTMLElement | null | undefined;
683
+ /**
684
+ * Enter (or Cmd/Ctrl+Enter) on this block while it is the keyboard
685
+ * navigation target — core's `onNavigationEnter` hook. Return true when the
686
+ * block handled it (e.g. opened a link); omit it, or return false, to let
687
+ * core put the caret in the block.
688
+ * @param event - the Enter keydown
689
+ * @param block - this block's per-block API
690
+ */
691
+ onNavigationEnter?: (event: KeyboardEvent, block: BlockAPI) => boolean;
677
692
  onRendered?: (block: BlockAPI) => void;
678
693
  /**
679
694
  * Fired ONCE per block instance, after the teleport's FIRST commit — the