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