Initial block picker

This commit is contained in:
Benjamin Bädorf 2020-05-24 22:00:14 +02:00
parent d49ea3e99f
commit 50a9606e86
No known key found for this signature in database
GPG key ID: 4406E80E13CD656C
19 changed files with 132 additions and 58 deletions

View file

@ -1,7 +1,6 @@
import { import {
defineComponent, defineComponent,
provide, provide,
computed,
reactive, reactive,
ref, ref,
PropType, PropType,
@ -17,6 +16,11 @@ import {
import SbBlock from '@internal/Block'; import SbBlock from '@internal/Block';
import SbLayout from '@user/Layout/index';
import SbParagraph from '@user/Paragraph/index';
import SbImage from '@user/Image/index';
import SbHeading from '@user/Heading/index';
export default defineComponent({ export default defineComponent({
name: 'schlechtenburg-main', name: 'schlechtenburg-main',
@ -32,26 +36,10 @@ export default defineComponent({
provide(ActiveBlock, activeBlock); provide(ActiveBlock, activeBlock);
const blockLibrary: BlockLibraryDefinition = reactive({ const blockLibrary: BlockLibraryDefinition = reactive({
'sb-layout': { 'sb-layout': SbLayout,
name: 'sb-layout', 'sb-image': SbImage,
edit: () => import('@user/Layout'), 'sb-paragraph': SbParagraph,
display: () => import('@user/Layout'), 'sb-heading': SbHeading,
},
'sb-image': {
name: 'sb-image',
edit: () => import('@user/Image'),
display: () => import('@user/Image'),
},
'sb-paragraph': {
name: 'sb-paragraph',
edit: () => import('@user/Paragraph'),
display: () => import('@user/Paragraph'),
},
'sb-heading': {
name: 'sb-heading',
edit: () => import('@user/Heading'),
display: () => import('@user/Heading'),
},
...props.customBlocks.reduce( ...props.customBlocks.reduce(
( (
blocks: BlockLibraryDefinition, blocks: BlockLibraryDefinition,

View file

@ -11,6 +11,7 @@ export const BlockLibrary = Symbol('Schlechtenburg block library');
export interface BlockDefinition { export interface BlockDefinition {
name: string; name: string;
getDefaultData: any;
edit: () => Promise<any>; edit: () => Promise<any>;
display: () => Promise<any>; display: () => Promise<any>;
} }

View file

@ -1,27 +1,37 @@
import { defineComponent } from '@vue/composition-api'; import { computed, defineComponent } from '@vue/composition-api';
import { useDynamicComponents } from './TreeElement'; import { useDynamicBlocks } from '../TreeElement';
import './BlockPicker.scss';
export default defineComponent({ export default defineComponent({
props: {}, props: {},
setup(props) { setup() {
const { customBlocks } = useDynamicComponents(props.components || {}); const { customBlocks } = useDynamicBlocks();
return { const blockList = computed(() => Object.keys(customBlocks).map((key) => customBlocks[key]));
customBlocks, console.log(customBlocks, blockList);
};
return { blockList };
}, },
render() { render() {
return ( return (
<div class="sb-block-picker"> <div class="sb-block-picker">
<component {...this.blockList.map((block: BlockDefinition) => (
class="sb-main" <button
v-for="child in children" type="button"
:key="child.id" {...{
:is="getComponent(child.name)" on: {
v-bind="child" click: ($event) => this.$emit('picked-block', {
/> name: block.name,
blockId: +(new Date()),
data: block.getDefaultData(),
}),
},
}}
>{block.name}</button>
))}
</div> </div>
); );
}, },

View file

@ -1,4 +1,6 @@
import { defineComponent } from '@vue/composition-api'; import { defineComponent } from '@vue/composition-api';
import { BlockDefinition } from '../TreeElement';
import BlockPicker from './BlockPicker';
import './BlockPlaceholder.scss'; import './BlockPlaceholder.scss';
@ -8,23 +10,13 @@ export default defineComponent({
render() { render() {
return ( return (
<div class="sb-block-placeholder"> <div class="sb-block-placeholder">
<button <BlockPicker
class="sb-block-placeholder__add"
type="button"
{...{ {...{
on: { on: {
click: () => this.$emit('insert-block', { 'picked-block': (block: BlockDefinition) => this.$emit('insert-block', block),
name: 'sb-paragraph',
blockId: +(new Date()),
data: {
value: '',
},
}),
}, },
}} }}
> />
{this.$slots.default ? this.$slots.default : 'Add a block'}
</button>
</div> </div>
); );
}, },

View file

@ -0,0 +1,8 @@
import { getDefaultData } from './util';
export default {
name: 'sb-heading',
getDefaultData,
edit: () => import('./edit'),
display: () => import('./edit'),
};

View file

@ -0,0 +1 @@
export const getDefaultData = () => ({});

View file

View file

@ -0,0 +1,8 @@
import { getDefaultData } from './util';
export default {
name: 'sb-image',
getDefaultData,
edit: () => import('./edit'),
display: () => import('./edit'),
};

View file

@ -0,0 +1 @@
export const getDefaultData = () => ({});

View file

@ -4,6 +4,7 @@ import {
computed, computed,
defineComponent, defineComponent,
watch, watch,
PropType,
} from '@vue/composition-api'; } from '@vue/composition-api';
import { import {
model, model,
@ -11,28 +12,38 @@ import {
useDynamicBlocks, useDynamicBlocks,
useActivation, useActivation,
BlockData, BlockData,
BlockDefinition,
} from '@components/TreeElement'; } from '@components/TreeElement';
import {
LayoutData,
LayoutProps,
getDefaultData,
} from './util';
import SbBlock from '@internal/Block'; import SbBlock from '@internal/Block';
import SbToolbar from '@internal/Toolbar'; import SbToolbar from '@internal/Toolbar';
import SbBlockPlaceholder from '@internal/BlockPlaceholder'; import SbBlockPlaceholder from '@internal/BlockPlaceholder';
import './Layout.scss'; import './style.scss';
export default defineComponent({ export default defineComponent({
name: 'sb-layout', name: 'sb-layout-edit',
model, model,
props: { props: {
...blockProps, ...blockProps,
data: {
type: (null as unknown) as PropType<LayoutData>,
default: getDefaultData,
},
}, },
setup(props: BlockProps, context) { setup(props: LayoutProps, context) {
const { getBlock } = useDynamicBlocks(); const { getBlock } = useDynamicBlocks();
const { isActive, activate } = useActivation(props.blockId); const { isActive, activate } = useActivation(props.blockId);
const localData = reactive({ const localData: LayoutData = reactive({
orientation: props.data.orientation, orientation: props.data.orientation,
children: [...props.data.children], children: [...props.data.children],
}); });

View file

@ -0,0 +1,8 @@
import { getDefaultData } from './util';
export default {
name: 'sb-layout',
getDefaultData,
edit: () => import('./edit'),
display: () => import('./edit'),
};

View file

@ -0,0 +1,18 @@
import {
BlockProps,
BlockDefinition,
} from '@components/TreeElement';
export interface LayoutData {
orientation: string;
children: BlockDefinition[];
}
export interface LayoutProps extends BlockProps {
data: LayoutData;
}
export const getDefaultData: () => LayoutData = () => ({
orientation: 'vertical',
children: [],
});

View file

@ -5,29 +5,38 @@ import {
Ref, Ref,
onMounted, onMounted,
watch, watch,
PropType,
} from '@vue/composition-api'; } from '@vue/composition-api';
import { import {
model, model,
blockProps, blockProps,
BlockProps,
useActivation, useActivation,
} from '@components/TreeElement'; } from '@components/TreeElement';
import SbBlock from '@internal/Block'; import {
getDefaultData,
ParagraphData,
ParagraphProps,
} from './util.ts';
import SbToolbar from '@internal/Toolbar'; import SbToolbar from '@internal/Toolbar';
import './Paragraph.scss'; import './style.scss';
export default defineComponent({ export default defineComponent({
name: 'sb-paragraph', name: 'sb-paragraph-edit',
model, model,
props: { props: {
...blockProps, ...blockProps,
data: {
type: (null as unknown) as PropType<ParagraphData>,
default: getDefaultData,
},
}, },
setup(props: BlockProps, context) { setup(props: ParagraphProps, context) {
const localData = reactive({ const localData = reactive({
value: props.data.value, value: props.data.value,
focused: false, focused: false,
@ -81,7 +90,7 @@ export default defineComponent({
context.emit('insert-block', { context.emit('insert-block', {
blockId, blockId,
name: 'sb-paragraph', name: 'sb-paragraph',
data: { value: '' }, data: getDefaultData(),
}); });
activate(blockId); activate(blockId);

View file

@ -0,0 +1,8 @@
import { getDefaultData } from './util';
export default {
name: 'sb-paragraph',
getDefaultData,
edit: () => import('./edit'),
display: () => import('./edit'),
};

View file

@ -0,0 +1,11 @@
import { BlockProps } from '@components/TreeElement';
export interface ParagraphData {
value: string;
}
export interface ParagraphProps extends BlockProps {
data: ParagraphData;
}
export const getDefaultData: () => ParagraphData = () => ({ value: '' });