diff --git a/packages/core/lib/blocks.ts b/packages/core/lib/blocks.ts index c25c949..4b0a2be 100644 --- a/packages/core/lib/blocks.ts +++ b/packages/core/lib/blocks.ts @@ -1,10 +1,18 @@ import { Component } from 'vue'; +export interface BlockTree { + name: string; + icon?: string; + children?: BlockTree[]; +} + export interface BlockDefinition { name: string; + icon?: string; getDefaultData: any; edit: Component; display: Component; + getChildren?: (block: Block) => Block[], } export interface BlockLibraryDefinition { diff --git a/packages/core/lib/components/Block.tsx b/packages/core/lib/components/Block.tsx index 2e62b01..e47dc41 100644 --- a/packages/core/lib/components/Block.tsx +++ b/packages/core/lib/components/Block.tsx @@ -73,7 +73,7 @@ export const SbBlock = defineComponent({ }; return () => { - const BlockComponent = getBlock(props.block.name) as any; + const BlockComponent = getBlock(props.block.name)?.[mode.value] as any; if (!BlockComponent) { const MissingBlock = SbMissingBlock[mode.value]; @@ -84,12 +84,10 @@ export const SbBlock = defineComponent({ } if (mode.value === SbMode.Display) { - return () => ( - - ); + return ; } return
(
Missing block: {props.name} diff --git a/packages/core/lib/components/ContextMenu.scss b/packages/core/lib/components/ContextMenu.scss index e69de29..6630898 100644 --- a/packages/core/lib/components/ContextMenu.scss +++ b/packages/core/lib/components/ContextMenu.scss @@ -0,0 +1,18 @@ +.sb-context { + position: relative; +} + +.sb-context-menu { + display: none; + flex-direction: column; + background: var(--grey-0); + border: 1px solid var(--grey-3); + top: 100%; + left: 0; + margin: 0; + z-index: var(--z-context-menu); + + &[open] { + display: flex; + } +} diff --git a/packages/core/lib/components/ContextMenu.tsx b/packages/core/lib/components/ContextMenu.tsx index b909200..fc62850 100644 --- a/packages/core/lib/components/ContextMenu.tsx +++ b/packages/core/lib/components/ContextMenu.tsx @@ -23,28 +23,33 @@ export const SbContextMenu = defineComponent({ setup(props: ContextMenuProps, context) { const opened = ref(false); - const close = () => { opened.value = false; } + const open = () => { opened.value = true; }; + const close = () => { opened.value = false; }; const closeOnEscape = ($event: KeyboardEvent) => { if ($event.key === 'Escape') { close(); } }; - const open = () => { - opened.value = true; - document.addEventListener('click', close); - document.addEventListener('keypress', closeOnEscape); - } - const toggle = () => { opened.value = !opened.value; } + const toggle = () => { opened.value ? close() : open() }; - watch(opened, () => { - if (!opened.value) { - document.removeEventListener('click', close); - document.removeEventListener('keypress', closeOnEscape); + watch(opened, (curr, prev) => { + if (curr === prev) { + return; + } + + if (!curr) { + document.body.removeEventListener('click', close); + document.body.removeEventListener('keypress', closeOnEscape); + } else { + setTimeout(() => { + document.body.addEventListener('click', close); + document.body.addEventListener('keypress', closeOnEscape); + }); } }); return () => ( -
+
{ context.slots.context({ opened, @@ -55,10 +60,12 @@ export const SbContextMenu = defineComponent({ Menu } { // Make sure clicks inside do not autoclose this + $event.stopPropagation(); }} > {context.slots.default({ diff --git a/packages/core/lib/components/MainMenu.tsx b/packages/core/lib/components/MainMenu.tsx index 21beba1..3894607 100644 --- a/packages/core/lib/components/MainMenu.tsx +++ b/packages/core/lib/components/MainMenu.tsx @@ -4,7 +4,7 @@ import { } from 'vue'; import { Block } from '../blocks'; -import { TreeBlockSelect } from './TreeBlockSelect'; +import { SbTreeBlockSelect } from './TreeBlockSelect'; import './MainMenu.scss'; @@ -25,8 +25,8 @@ export const SbMainMenu = defineComponent({ setup(props: MainMenuProps, context) { return () => (
-
); diff --git a/packages/core/lib/components/Schlechtenburg.tsx b/packages/core/lib/components/Schlechtenburg.tsx index 9fae3e7..b430c9f 100644 --- a/packages/core/lib/components/Schlechtenburg.tsx +++ b/packages/core/lib/components/Schlechtenburg.tsx @@ -67,18 +67,16 @@ export const Schlechtenburg = defineComponent({ provide(BlockLibrary, blockLibrary); - watch(props.block, () => { - console.log('Update', props.block); - }); - return () => (
- + { + mode.value === SbMode.Edit + ? + : null + } { + const getBlockChildren = getBlock(block.name)?.getChildren; + // TODO: vue-jxs apparently cannot parse arrow functions here + const getChildren = getBlockChildren || function ({ data }) { return data?.children; }; + const children = getChildren(block) || []; + return { + name: block.name, + children: children.map(getTreeForBlock), + }; + }; + + const tree = computed(() => getTreeForBlock(props.block)); + + const treeToHtml = (tree: BlockTree) =>
  • + {tree.name} + {tree.children.length ?
      {tree.children.map(treeToHtml)}
    : null} +
  • ; + return () => ( Tree, - default: () =>
      -
    • Test
    • -
    , + default: () =>
      {treeToHtml(tree.value)}
    , }} - >
    + /> ); }, }); diff --git a/packages/core/lib/use-dynamic-blocks.ts b/packages/core/lib/use-dynamic-blocks.ts index 6dfa2f3..8baf84e 100644 --- a/packages/core/lib/use-dynamic-blocks.ts +++ b/packages/core/lib/use-dynamic-blocks.ts @@ -10,7 +10,7 @@ export const BlockLibrary = Symbol('Schlechtenburg block library'); export function useDynamicBlocks() { const mode = inject(Mode, ref(SbMode.Edit)); const customBlocks: BlockLibraryDefinition = inject(BlockLibrary, reactive({})); - const getBlock = (name: string) => customBlocks[name]?.[mode.value]; + const getBlock = (name: string) => customBlocks[name]; return { mode, diff --git a/packages/image/lib/index.ts b/packages/image/lib/index.ts index 1d127e1..8102655 100644 --- a/packages/image/lib/index.ts +++ b/packages/image/lib/index.ts @@ -6,4 +6,5 @@ export default { getDefaultData, edit: defineAsyncComponent(() => import('./edit')), display: defineAsyncComponent(() => import('./display')), + getChildren: (block) => [ block.data.description ], }; diff --git a/src/App.tsx b/src/App.tsx index 2bd8549..80da5f2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -49,13 +49,19 @@ export default defineComponent({ SbParagraph, ]} key="edit" - mode="edit" + mode={SbMode.Edit} />; - case SbMode.Edit: + case SbMode.Display: return ; case 'data': return
    { JSON.stringify(block, null, 2) }
    ; diff --git a/src/main.scss b/src/main.scss index c6f8905..dec116a 100644 --- a/src/main.scss +++ b/src/main.scss @@ -22,6 +22,8 @@ html { --fg: var(--black); --interact: #3f9cff; + + --z-context-menu: 3000; } body {