Improve Interface naming, fix deactivate on document click

This commit is contained in:
Benjamin Bädorf 2022-03-11 17:50:50 +01:00
parent 9289083a59
commit 01c2644a36
No known key found for this signature in database
GPG key ID: 4406E80E13CD656C
19 changed files with 93 additions and 71 deletions

View file

@ -6,7 +6,7 @@ import {
ref,
Ref,
} from 'vue';
import { BlockData } from '../types';
import { IBlockData } from '../types';
import { SbMode } from '../mode';
import { useResizeObserver, SymBlockDimensions } from '../use-resize-observer';
import { useActivation } from '../use-activation';
@ -22,7 +22,7 @@ export const SbBlock = defineComponent({
props: {
block: {
type: (null as unknown) as PropType<BlockData<any>>,
type: (null as unknown) as PropType<IBlockData<any>>,
required: true,
},
sortable: {

View file

@ -4,7 +4,7 @@ import {
defineComponent,
} from 'vue';
import { useDynamicBlocks } from '../use-dynamic-blocks';
import { BlockDefinition } from '../types';
import { IBlockDefinition } from '../types';
import { SbButton } from './Button';
import { SbContextMenu } from './ContextMenu';
@ -19,11 +19,13 @@ export const SbBlockPicker = defineComponent({
},
setup(props, context) {
const open = ref(false);
const { customBlocks } = useDynamicBlocks();
const blockList = computed(() => Object.keys(customBlocks).map((key) => customBlocks[key]));
const selectBlock = (block: BlockDefinition<any>) => () => {
const selectBlock = (block: IBlockDefinition<any>) => () => {
open.value = false;
props.onPickedBlock({
name: block.name,
@ -40,7 +42,7 @@ export const SbBlockPicker = defineComponent({
context: (slotContext) => context.slots.context
? context.slots.context(slotContext)
: <SbButton {...{ onClick: slotContext.toggle }}>Insert a block</SbButton>,
default: ({ close }: { close: Function }) => blockList.value.map((block: BlockDefinition<any>) => (
default: ({ close }: { close: Function }) => blockList.value.map((block: IBlockDefinition<any>) => (
<SbButton
{...{
type: 'button',

View file

@ -1,5 +1,5 @@
import { defineComponent } from 'vue';
import { BlockData } from '../types';
import { IBlockData } from '../types';
import { SbBlockPicker } from './BlockPicker';
@ -16,7 +16,7 @@ export const SbBlockPlaceholder = defineComponent({
return () => (
<div class="sb-block-placeholder">
<SbBlockPicker
onPickedBlock={(block: BlockData<any>) => props.onInsertBlock(block)}
onPickedBlock={(block: IBlockData<any>) => props.onInsertBlock(block)}
/>
</div>
);

View file

@ -1,5 +1,5 @@
import { defineComponent } from 'vue';
import { TreeNode } from '../types';
import { ITreeNode } from '../types';
import { useBlockTree } from '../use-block-tree';
import { useActivation } from '../use-activation';

View file

@ -2,7 +2,7 @@ import {
defineComponent,
PropType,
} from 'vue';
import { BlockData } from '../types';
import { IBlockData } from '../types';
import { SbTreeBlockSelect } from './TreeBlockSelect';
import { SbGlobalInsert } from './GlobalInsert';
@ -13,7 +13,7 @@ export const SbMainMenu = defineComponent({
props: {
block: {
type: (null as unknown) as PropType<BlockData<any>>,
type: (null as unknown) as PropType<IBlockData<any>>,
required: true,
},
},

View file

@ -7,10 +7,10 @@ import {
Ref,
} from 'vue';
import {
BlockData,
BlockDefinition,
BlockLibrary,
TreeNode,
IBlockData,
IBlockDefinition,
IBlockLibrary,
ITreeNode,
} from '../types';
import { model } from '../block-helpers';
import { Mode, SbMode } from '../mode';
@ -36,11 +36,11 @@ export const SbMain = defineComponent({
props: {
customBlocks: {
type: Array as PropType<BlockDefinition<any>[]>,
type: Array as PropType<IBlockDefinition<any>[]>,
default: () => [],
},
block: {
type: Object as PropType<BlockData<any>>,
type: Object as PropType<IBlockData<any>>,
required: true,
},
onUpdate: { type: Function, default: () => {} },
@ -63,14 +63,14 @@ export const SbMain = defineComponent({
const activeBlock = ref(null);
provide(SymActiveBlock, activeBlock);
const blockTree: Ref<TreeNode|null> = ref(null);
const blockTree: Ref<ITreeNode|null> = ref(null);
provide(SymBlockTree, blockTree);
provide(SymBlockTreeRegister, (block: TreeNode) => { blockTree.value = block; });
provide(SymBlockTreeRegister, (block: ITreeNode) => { blockTree.value = block; });
provide(SymBlockTreeUnregister, () => { blockTree.value = null; });
const blockLibrary: BlockLibrary = shallowReactive({
const blockLibrary: IBlockLibrary = shallowReactive({
...props.customBlocks.reduce(
(blocks: BlockLibrary, block: BlockDefinition<any>) => ({ ...blocks, [block.name]: block }),
(blocks: IBlockLibrary, block: IBlockDefinition<any>) => ({ ...blocks, [block.name]: block }),
{},
),
});

View file

@ -1,5 +1,5 @@
import { defineComponent } from 'vue';
import { TreeNode } from '../types';
import { ITreeNode } from '../types';
import { useBlockTree } from '../use-block-tree';
import { useActivation } from '../use-activation';
@ -18,7 +18,7 @@ export const SbTreeBlockSelect = defineComponent({
activeBlockId,
} = useActivation();
const treeToHtml = (tree: TreeNode, close: Function) => <li
const treeToHtml = (tree: ITreeNode, close: Function) => <li
class={{
'sb-tree-block-select__block': true,
'sb-tree-block-select__block_active': activeBlockId.value === tree.id,
@ -34,7 +34,7 @@ export const SbTreeBlockSelect = defineComponent({
>{tree.name}</button>
{tree.children?.length
? <ul class="sb-tree-block-select__list">
{tree.children?.map((child: TreeNode) => treeToHtml(child, close))}
{tree.children?.map((child: ITreeNode) => treeToHtml(child, close))}
</ul>
: null
}
@ -48,7 +48,7 @@ export const SbTreeBlockSelect = defineComponent({
context: ({ toggle }: { toggle: Function }) => <SbButton {...{ onClick: toggle }}>Tree</SbButton>,
default: ({ close }: { close: Function }) => <ul
class="sb-tree-block-select__list sb-tree-block-select__list_base"
>{treeToHtml(blockTree.value as TreeNode, close)}</ul>,
>{treeToHtml(blockTree.value as ITreeNode, close)}</ul>,
}}
/>
: ''

View file

@ -1,37 +1,37 @@
import { Component } from 'vue';
export interface TreeNode {
export interface ITreeNode {
id: string;
name: string;
icon?: string;
children: TreeNode[];
children: ITreeNode[];
}
export interface BlockData<T> {
export interface IBlockData<T> {
id: string;
name: string;
data: T;
}
export interface BlockProps<T> {
export interface IBlockProps<T> {
blockId: string;
data?: T,
onUpdate?: (b?: BlockData<T>) => void;
onPrependBlock?: (b?: BlockData<T>) => void;
onAppendBlock?: (b?: BlockData<T>) => void;
onUpdate?: (b?: IBlockData<T>) => void;
onPrependBlock?: (b?: IBlockData<T>) => void;
onAppendBlock?: (b?: IBlockData<T>) => void;
onRemoveSelf?: () => void;
onActivateNext?: () => void;
onActivatePrevious?: () => void;
}
export interface BlockDefinition<T> {
export interface IBlockDefinition<T> {
name: string;
icon?: string;
getDefaultData: T;
edit: Component<BlockProps<T>>;
display: Component<BlockProps<T>>;
edit: Component<IBlockProps<T>>;
display: Component<IBlockProps<T>>;
}
export interface BlockLibrary {
[name: string]: BlockDefinition<any>;
export interface IBlockLibrary {
[name: string]: IBlockDefinition<any>;
}

View file

@ -3,15 +3,34 @@ import {
ref,
inject,
computed,
onBeforeUnmount,
} from 'vue';
export const SymActiveBlock = Symbol('Schlechtenburg active block');
export function useActivation(currentBlockId: string|null = null) {
const activeBlockId: Ref<string|null> = inject(SymActiveBlock, ref(null));
const isActive = computed(() => activeBlockId.value === currentBlockId);
const activate = (id?: string|null) => {
activeBlockId.value = id !== undefined ? id : currentBlockId;
const deactivate = (id: string|null = currentBlockId) => {
if (activeBlockId.value !== id) {
return;
}
activeBlockId.value = null;
};
const deactivateCb = (_:Event) => deactivate();
onBeforeUnmount(() => {
document.removeEventListener('click', deactivateCb);
})
const activate = (id: string|null = currentBlockId) => {
document.addEventListener('click', deactivateCb, { once: true });
activeBlockId.value = id;
};
const requestActivation = () => {
if (activeBlockId.value) {
return;
@ -24,6 +43,7 @@ export function useActivation(currentBlockId: string|null = null) {
activeBlockId,
isActive,
activate,
deactivate,
requestActivation,
};
}

View file

@ -7,8 +7,8 @@ import {
onUnmounted,
} from 'vue';
import {
TreeNode,
BlockData,
ITreeNode,
IBlockData,
} from './types';
export const SymBlockTree= Symbol('Schlechtenburg block tree');
@ -16,11 +16,11 @@ export const SymBlockTreeRegister = Symbol('Schlechtenburg block tree register')
export const SymBlockTreeUnregister = Symbol('Schlechtenburg block tree unregister');
export function useBlockTree() {
const blockTree: Ref<TreeNode|null> = inject(SymBlockTree, ref(null));
const registerWithParent = inject(SymBlockTreeRegister, (_: TreeNode) => {});
const unregisterWithParent = inject(SymBlockTreeUnregister, (_: TreeNode) => {});
const blockTree: Ref<ITreeNode|null> = inject(SymBlockTree, ref(null));
const registerWithParent = inject(SymBlockTreeRegister, (_: ITreeNode) => {});
const unregisterWithParent = inject(SymBlockTreeUnregister, (_: ITreeNode) => {});
const self: TreeNode = reactive({
const self: ITreeNode = reactive({
id: '',
name: '',
icon: '',
@ -28,8 +28,8 @@ export function useBlockTree() {
});
// Provide a registration function to child blocks
provide(SymBlockTreeRegister, (block: TreeNode) => {
if (self.children.find((child: TreeNode) => child.id === block.id)) {
provide(SymBlockTreeRegister, (block: ITreeNode) => {
if (self.children.find((child: ITreeNode) => child.id === block.id)) {
return;
}
@ -40,11 +40,11 @@ export function useBlockTree() {
});
// Provide an unregistration function to child blocks
provide(SymBlockTreeUnregister, ({ id }: TreeNode) => {
self.children = self.children.filter((child: TreeNode) => child.id !== id);
provide(SymBlockTreeUnregister, ({ id }: ITreeNode) => {
self.children = self.children.filter((child: ITreeNode) => child.id !== id);
});
const register = (block: BlockData<any>) => {
const register = (block: IBlockData<any>) => {
if (!block.id) {
throw new Error(`Cannot register a block without an id: ${JSON.stringify(block)}`);
}

View file

@ -3,13 +3,13 @@ import {
inject,
reactive,
} from 'vue';
import { BlockLibrary } from './types';
import { IBlockLibrary } from './types';
import { Mode, SbMode } from './mode';
export const SymBlockLibrary = Symbol('Schlechtenburg block library');
export function useDynamicBlocks() {
const mode = inject(Mode, ref(SbMode.Edit));
const customBlocks: BlockLibrary = inject(SymBlockLibrary, reactive({}));
const customBlocks: IBlockLibrary = inject(SymBlockLibrary, reactive({}));
const getBlock = (name: string) => customBlocks[name];
return {

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
{"version":3,"file":"edit.a95f3ab1.js","sources":["../../../image/lib/edit.tsx"],"sourcesContent":["import {\n defineComponent,\n reactive,\n ref,\n Ref,\n watch,\n PropType,\n} from 'vue';\nimport {\n model,\n SbToolbar,\n SbButton,\n SbBlock,\n BlockData,\n} from '@schlechtenburg/core';\nimport { ParagraphData } from '@schlechtenburg/paragraph';\nimport {\n getDefaultData,\n ImageData,\n} from './util';\n\nimport './style.scss';\n\nexport default defineComponent({\n name: 'sb-image-edit',\n\n model,\n\n props: {\n onUpdate: { type: Function, default: () => {} },\n data: {\n type: (null as unknown) as PropType<ImageData>,\n default: getDefaultData,\n },\n },\n\n setup(props) {\n const localData = reactive({\n src: props.data.src,\n alt: props.data.alt,\n description: props.data.description,\n });\n\n const fileInput: Ref<null|HTMLInputElement> = ref(null);\n\n watch(() => props.data, () => {\n localData.src = props.data.src;\n localData.alt = props.data.alt;\n localData.description = props.data.description;\n });\n\n const selectImage = () => {\n if (fileInput.value) {\n fileInput.value.click();\n }\n };\n\n const onImageSelect = () => {\n if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {\n const reader = new FileReader();\n reader.addEventListener('load', () => {\n const src = reader?.result?.toString();\n if (!src) {\n throw new Error('Couldn\\'t load image src');\n }\n\n props.onUpdate({\n src,\n alt: props.data.alt,\n description: props.data.description,\n });\n });\n\n reader.readAsDataURL(fileInput.value.files[0]);\n }\n };\n\n const onDescriptionUpdate = (description: BlockData<ParagraphData>) => {\n props.onUpdate({\n ...props.data,\n description,\n });\n };\n\n return () => (\n <figure class=\"sb-image\">\n <SbToolbar>\n {localData.src\n ? <SbButton {...{ onClick: selectImage }}>Select Image</SbButton>\n : null}\n <input\n type=\"file\"\n ref={fileInput}\n style=\"display: none;\"\n onInput={onImageSelect}\n />\n </SbToolbar>\n {localData.src\n ? <>\n <img\n src={localData.src}\n alt={localData.alt}\n class=\"sb-image__content\"\n />\n <SbBlock\n block={localData.description}\n onUpdate={(updated: BlockData<ParagraphData>) => onDescriptionUpdate(updated)}\n />\n </>\n : <SbButton {...{ onClick: selectImage }}>Select Image</SbButton>\n }\n </figure>\n );\n },\n});\n"],"names":["defineComponent","name","model","props","onUpdate","type","Function","default","data","getDefaultData","setup","localData","reactive","src","alt","description","fileInput","ref","selectImage","value","click","onImageSelect","files","length","reader","FileReader","addEventListener","result","toString","Error","readAsDataURL","onClick","onDescriptionUpdate","updated","__assign"],"mappings":"8dAuBA,MAAeA,EAAgB,CAC7BC,KAAM,gBAENC,MAAAA,EAEAC,MAAO,CACLC,SAAU,CAAEC,KAAMC,SAAUC,QAAS,QACrCC,KAAM,CACJH,KAAO,KACPE,QAASE,IAIbC,MAAMP,SACEQ,EAAYC,EAAS,CACzBC,IAAKV,EAAMK,KAAKK,IAChBC,IAAKX,EAAMK,KAAKM,IAChBC,YAAaZ,EAAMK,KAAKO,cAGpBC,EAAwCC,EAAI,SAE5C,IAAMd,EAAMK,OAAM,OACZK,IAAMV,EAAMK,KAAKK,MACjBC,IAAMX,EAAMK,KAAKM,MACjBC,YAAcZ,EAAMK,KAAKO,qBAG/BG,EAAc,KACdF,EAAUG,SACFA,MAAMC,SAIdC,EAAgB,QAChBL,EAAUG,OAASH,EAAUG,MAAMG,OAASN,EAAUG,MAAMG,MAAMC,OAAQ,OACtEC,EAAS,IAAIC,aACZC,iBAAiB,QAAQ,iBACxBb,EAAMW,0BAAQG,iBAAQC,eACvBf,QACG,IAAIgB,MAAM,6BAGZzB,SAAS,CACbS,IAAAA,EACAC,IAAKX,EAAMK,KAAKM,IAChBC,YAAaZ,EAAMK,KAAKO,mBAIrBe,cAAcd,EAAUG,MAAMG,MAAM,YAWxC,sBACS,oCAETX,EAAUE,SACSkB,QAASb,sCACzB,qBAEG,WACAF,QACC,yBACGK,YAGZV,EAAUE,2BAGEF,EAAUE,QACVF,EAAUG,UACT,sCAGCH,EAAUI,yBACgCiB,SAAoBC,SA5BzE7B,SAAS8B,OACV/B,EAAMK,MADI,CAEbO,YAAAA,KAHyBA,qBAgCLgB,QAASb"}
{"version":3,"file":"edit.a95f3ab1.js","sources":["../../../image/lib/edit.tsx"],"sourcesContent":["import {\n defineComponent,\n reactive,\n ref,\n Ref,\n watch,\n PropType,\n} from 'vue';\nimport {\n model,\n SbToolbar,\n SbButton,\n SbBlock,\n IBlockData,\n} from '@schlechtenburg/core';\nimport { ParagraphData } from '@schlechtenburg/paragraph';\nimport {\n getDefaultData,\n ImageData,\n} from './util';\n\nimport './style.scss';\n\nexport default defineComponent({\n name: 'sb-image-edit',\n\n model,\n\n props: {\n onUpdate: { type: Function, default: () => {} },\n data: {\n type: (null as unknown) as PropType<ImageData>,\n default: getDefaultData,\n },\n },\n\n setup(props) {\n const localData = reactive({\n src: props.data.src,\n alt: props.data.alt,\n description: props.data.description,\n });\n\n const fileInput: Ref<null|HTMLInputElement> = ref(null);\n\n watch(() => props.data, () => {\n localData.src = props.data.src;\n localData.alt = props.data.alt;\n localData.description = props.data.description;\n });\n\n const selectImage = () => {\n if (fileInput.value) {\n fileInput.value.click();\n }\n };\n\n const onImageSelect = () => {\n if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {\n const reader = new FileReader();\n reader.addEventListener('load', () => {\n const src = reader?.result?.toString();\n if (!src) {\n throw new Error('Couldn\\'t load image src');\n }\n\n props.onUpdate({\n src,\n alt: props.data.alt,\n description: props.data.description,\n });\n });\n\n reader.readAsDataURL(fileInput.value.files[0]);\n }\n };\n\n const onDescriptionUpdate = (description: IBlockData<ParagraphData>) => {\n props.onUpdate({\n ...props.data,\n description,\n });\n };\n\n return () => (\n <figure class=\"sb-image\">\n <SbToolbar>\n {localData.src\n ? <SbButton {...{ onClick: selectImage }}>Select Image</SbButton>\n : null}\n <input\n type=\"file\"\n ref={fileInput}\n style=\"display: none;\"\n onInput={onImageSelect}\n />\n </SbToolbar>\n {localData.src\n ? <>\n <img\n src={localData.src}\n alt={localData.alt}\n class=\"sb-image__content\"\n />\n <SbBlock\n block={localData.description}\n onUpdate={(updated: IBlockData<ParagraphData>) => onDescriptionUpdate(updated)}\n />\n </>\n : <SbButton {...{ onClick: selectImage }}>Select Image</SbButton>\n }\n </figure>\n );\n },\n});\n"],"names":["defineComponent","name","model","props","onUpdate","type","Function","default","data","getDefaultData","setup","localData","reactive","src","alt","description","fileInput","ref","selectImage","value","click","onImageSelect","files","length","reader","FileReader","addEventListener","result","toString","Error","readAsDataURL","onClick","onDescriptionUpdate","updated","__assign"],"mappings":"8dAuBA,MAAeA,EAAgB,CAC7BC,KAAM,gBAENC,MAAAA,EAEAC,MAAO,CACLC,SAAU,CAAEC,KAAMC,SAAUC,QAAS,QACrCC,KAAM,CACJH,KAAO,KACPE,QAASE,IAIbC,MAAMP,SACEQ,EAAYC,EAAS,CACzBC,IAAKV,EAAMK,KAAKK,IAChBC,IAAKX,EAAMK,KAAKM,IAChBC,YAAaZ,EAAMK,KAAKO,cAGpBC,EAAwCC,EAAI,SAE5C,IAAMd,EAAMK,OAAM,OACZK,IAAMV,EAAMK,KAAKK,MACjBC,IAAMX,EAAMK,KAAKM,MACjBC,YAAcZ,EAAMK,KAAKO,qBAG/BG,EAAc,KACdF,EAAUG,SACFA,MAAMC,SAIdC,EAAgB,QAChBL,EAAUG,OAASH,EAAUG,MAAMG,OAASN,EAAUG,MAAMG,MAAMC,OAAQ,OACtEC,EAAS,IAAIC,aACZC,iBAAiB,QAAQ,iBACxBb,EAAMW,0BAAQG,iBAAQC,eACvBf,QACG,IAAIgB,MAAM,6BAGZzB,SAAS,CACbS,IAAAA,EACAC,IAAKX,EAAMK,KAAKM,IAChBC,YAAaZ,EAAMK,KAAKO,mBAIrBe,cAAcd,EAAUG,MAAMG,MAAM,YAWxC,sBACS,oCAETX,EAAUE,SACSkB,QAASb,sCACzB,qBAEG,WACAF,QACC,yBACGK,YAGZV,EAAUE,2BAGEF,EAAUE,QACVF,EAAUG,UACT,sCAGCH,EAAUI,yBACgCiB,SAAoBC,SA5BzE7B,SAAS8B,OACV/B,EAAMK,MADI,CAEbO,YAAAA,KAHyBA,qBAgCLgB,QAASb"}

File diff suppressed because one or more lines are too long

View file

@ -6,7 +6,7 @@ import {
ref,
} from 'vue';
import { SbMain, BlockData, SbMode } from '@schlechtenburg/core';
import { SbMain, IBlockData, SbMode } from '@schlechtenburg/core';
import SbLayout from '@schlechtenburg/layout';
import SbHeading from '@schlechtenburg/heading';
@ -20,7 +20,7 @@ export default defineComponent({
setup() {
const activeTab = ref('edit');
const block: BlockData<any> = reactive({
const block: IBlockData<any> = reactive({
name: 'none',
id: '0',
data: null,
@ -39,7 +39,7 @@ export default defineComponent({
case SbMode.Edit:
return <SbMain
block={block}
onUpdate={(newBlock: BlockData<any>) => {
onUpdate={(newBlock: IBlockData<any>) => {
block.data = newBlock.data;
}}
customBlocks={[

View file

@ -11,7 +11,7 @@ import {
SbToolbar,
SbButton,
SbBlock,
BlockData,
IBlockData,
} from '@schlechtenburg/core';
import { ParagraphData } from '@schlechtenburg/paragraph';
import {
@ -75,7 +75,7 @@ export default defineComponent({
}
};
const onDescriptionUpdate = (description: BlockData<ParagraphData>) => {
const onDescriptionUpdate = (description: IBlockData<ParagraphData>) => {
props.onUpdate({
...props.data,
description,
@ -104,7 +104,7 @@ export default defineComponent({
/>
<SbBlock
block={localData.description}
onUpdate={(updated: BlockData<ParagraphData>) => onDescriptionUpdate(updated)}
onUpdate={(updated: IBlockData<ParagraphData>) => onDescriptionUpdate(updated)}
/>
</>
: <SbButton {...{ onClick: selectImage }}>Select Image</SbButton>

View file

@ -1,5 +1,5 @@
import {
BlockData,
IBlockData,
generateBlockId,
} from '@schlechtenburg/core';
import {
@ -11,7 +11,7 @@ import {
export interface ImageData {
src: string;
alt: string;
description: BlockData<ParagraphData>;
description: IBlockData<ParagraphData>;
}
export const getDefaultData: () => ImageData = () => ({

View file

@ -7,7 +7,7 @@ import {
} from 'vue';
import {
model,
BlockData,
IBlockData,
useActivation,
SbBlock,
@ -61,7 +61,7 @@ export default defineComponent({
});
};
const onChildUpdate = (child: BlockData<any>, updated: BlockData<any>) => {
const onChildUpdate = (child: IBlockData<any>, updated: IBlockData<any>) => {
const index = localData.children.indexOf(child);
if (index === -1) {
return;
@ -78,7 +78,7 @@ export default defineComponent({
});
};
const appendBlock = (block: BlockData<any>) => {
const appendBlock = (block: IBlockData<any>) => {
localData.children = [
...localData.children,
block,
@ -87,7 +87,7 @@ export default defineComponent({
activate(block.id);
};
const insertBlock = (index: number, block: BlockData<any>) => {
const insertBlock = (index: number, block: IBlockData<any>) => {
localData.children = [
...localData.children.slice(0, index + 1),
block,
@ -170,10 +170,10 @@ export default defineComponent({
{...{ key: child.id }}
data-order={index}
block={child}
onUpdate={(updated: BlockData<any>) => onChildUpdate(child, updated)}
onUpdate={(updated: IBlockData<any>) => onChildUpdate(child, updated)}
onRemoveSelf={() => removeBlock(index)}
onPrependBlock={(block: BlockData<any>) => insertBlock(index - 1, block)}
onAppendBlock={(block: BlockData<any>) => insertBlock(index, block)}
onPrependBlock={(block: IBlockData<any>) => insertBlock(index - 1, block)}
onAppendBlock={(block: IBlockData<any>) => insertBlock(index, block)}
onActivatePrevious={() => activateBlock(index - 1,)}
onActivateNext={() => activateBlock(index + 1,)}
>

View file

@ -1,8 +1,8 @@
import { BlockData } from '@schlechtenburg/core';
import { IBlockData } from '@schlechtenburg/core';
export interface LayoutData {
orientation: string;
children: BlockData<any>[];
children: IBlockData<any>[];
}
export const getDefaultData: () => LayoutData = () => ({