- {...blockList.value.map((block: BlockDefinition) => (
-
- ))}
+
$event.stopPropagation()}
+ >
+ {
+ open.value = true;
+ console.log(open);
+ }}
+ >Add a block
+ {
+ open.value = false;
+ }}
+ >
+ {...blockList.value.map((block: BlockDefinition) => (
+ {block.name}
+ ))}
+
);
},
diff --git a/src/components/internal/Button.scss b/src/components/internal/Button.scss
new file mode 100644
index 0000000..625ae48
--- /dev/null
+++ b/src/components/internal/Button.scss
@@ -0,0 +1,10 @@
+.sb-button {
+ border: 0;
+ padding: 8px 12px;
+ background-color: var(--grey-0);
+ border: 1px solid var(--grey-2);
+
+ &:hover {
+ border: 1px solid var(--interact);
+ }
+}
diff --git a/src/components/internal/Button.tsx b/src/components/internal/Button.tsx
new file mode 100644
index 0000000..4d447b2
--- /dev/null
+++ b/src/components/internal/Button.tsx
@@ -0,0 +1,23 @@
+import { defineComponent } from '@vue/composition-api';
+
+import './Button.scss';
+
+export default defineComponent({
+ name: 'sb-button',
+
+ inheritAttrs: false,
+
+ setup(props, context) {
+ return () => (
+
+ );
+ },
+});
diff --git a/src/components/internal/Modal.scss b/src/components/internal/Modal.scss
new file mode 100644
index 0000000..c336a80
--- /dev/null
+++ b/src/components/internal/Modal.scss
@@ -0,0 +1,31 @@
+.sb-modal {
+ &__overlay {
+ background-color: var(--grey-3-t);
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ padding: 10vh 10vw;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ &__content {
+ width: 900px;
+ max-width: 100%;
+ height: auto;
+ max-height: 100%;
+ background-color: var(--grey-0);
+ padding: 24px 32px;
+ }
+
+ &_open #{&}__overlay {
+ opacity: 1;
+ pointer-events: all;
+ }
+}
diff --git a/src/components/internal/Modal.tsx b/src/components/internal/Modal.tsx
new file mode 100644
index 0000000..75298ef
--- /dev/null
+++ b/src/components/internal/Modal.tsx
@@ -0,0 +1,45 @@
+import {
+ defineComponent,
+ computed,
+ ref,
+} from '@vue/composition-api';
+
+import './Modal.scss';
+
+export default defineComponent({
+ name: 'sb-modal',
+
+ props: {
+ open: {
+ type: Boolean,
+ default: false,
+ },
+ eventClose: {
+ type: (Function as unknown) as () => void,
+ default: () => () => undefined,
+ },
+ },
+
+ setup(props, context) {
+ const classes = computed(() => ({
+ 'sb-modal': true,
+ 'sb-modal_open': props.open,
+ }));
+
+ return () => (
+
+
{
+ $event.stopPropagation();
+ props.eventClose();
+ }}
+ >
+
+ {context.slots.default()}
+
+
+
+ );
+ },
+});
diff --git a/src/components/internal/Toolbar.scss b/src/components/internal/Toolbar.scss
index 91e998e..5266a67 100644
--- a/src/components/internal/Toolbar.scss
+++ b/src/components/internal/Toolbar.scss
@@ -1,7 +1,7 @@
.sb-toolbar {
position: absolute;
bottom: 100%;
- width: 100%;
- height: 40px;
- background-color: var(--grey-1);
+ width: auto;
+ max-width: 100%;
+ height: auto;
}
diff --git a/src/components/user/Image/edit.tsx b/src/components/user/Image/edit.tsx
index ffee726..9df58d3 100644
--- a/src/components/user/Image/edit.tsx
+++ b/src/components/user/Image/edit.tsx
@@ -34,7 +34,7 @@ export default defineComponent({
},
},
- setup(props: ImageProps) {
+ setup(props: ImageProps, context) {
const localData = reactive({
src: props.data.src,
alt: props.data.alt,
@@ -56,7 +56,9 @@ export default defineComponent({
const onImageSelect = () => {
if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {
- localData.src = window.URL.createObjectURL(fileInput.value.files[0]);
+ context.emit('update', {
+ src: window.URL.createObjectURL(fileInput.value.files[0]),
+ });
}
};
diff --git a/src/components/user/Layout/display.tsx b/src/components/user/Layout/display.tsx
new file mode 100644
index 0000000..ccc4839
--- /dev/null
+++ b/src/components/user/Layout/display.tsx
@@ -0,0 +1,57 @@
+import {
+ reactive,
+ computed,
+ defineComponent,
+ watch,
+ PropType,
+} from '@vue/composition-api';
+import {
+ model,
+ blockProps,
+ useActivation,
+ BlockData,
+} from '@components/TreeElement';
+
+import SbBlock from '@internal/Block';
+import SbToolbar from '@internal/Toolbar';
+import SbBlockPlaceholder from '@internal/BlockPlaceholder';
+
+import {
+ LayoutData,
+ LayoutProps,
+ getDefaultData,
+} from './util';
+
+import './style.scss';
+
+export default defineComponent({
+ name: 'sb-layout-display',
+
+ model,
+
+ props: {
+ ...blockProps,
+ data: {
+ type: (null as unknown) as PropType
,
+ default: getDefaultData,
+ },
+ },
+
+ setup(props: LayoutProps, context) {
+ const classes = computed(() => ({
+ 'sb-layout': true,
+ [`sb-layout_${props.data.orientation}`]: true,
+ }));
+
+ return () => (
+
+ {...props.data.children.map((child, index) => (
+
+ ))}
+
+ );
+ },
+});
diff --git a/src/components/user/Layout/edit.tsx b/src/components/user/Layout/edit.tsx
index c17c026..c94cf0d 100644
--- a/src/components/user/Layout/edit.tsx
+++ b/src/components/user/Layout/edit.tsx
@@ -7,12 +7,13 @@ import {
} from '@vue/composition-api';
import {
model,
- blockProps,
useActivation,
BlockData,
+ blockProps,
} from '@components/TreeElement';
import SbBlock from '@internal/Block';
+import SbButton from '@internal/Button';
import SbToolbar from '@internal/Toolbar';
import SbBlockPlaceholder from '@internal/BlockPlaceholder';
@@ -31,6 +32,10 @@ export default defineComponent({
props: {
...blockProps,
+ eventUpdate: {
+ type: (Function as unknown) as (b?: LayoutData) => void,
+ default: () => () => undefined,
+ },
data: {
type: (null as unknown) as PropType,
default: getDefaultData,
@@ -56,14 +61,14 @@ export default defineComponent({
}));
const toggleOrientation = () => {
- context.emit('update', {
+ props.eventUpdate({
orientation: localData.orientation === 'vertical' ? 'horizontal' : 'vertical',
});
};
const onChildUpdate = (child: BlockData, updated: BlockData) => {
const index = localData.children.indexOf(child);
- context.emit('update', {
+ props.eventUpdate({
children: [
...localData.children.slice(0, index),
{
@@ -76,7 +81,7 @@ export default defineComponent({
};
const appendBlock = (block: BlockData) => {
- context.emit('update', {
+ props.eventUpdate({
children: [
...localData.children,
block,
@@ -99,14 +104,14 @@ export default defineComponent({
return () => (
-
+ >{localData.orientation}
{...localData.children.map((child, index) => (
diff --git a/src/components/user/Layout/index.ts b/src/components/user/Layout/index.ts
index 3539233..a8cfd47 100644
--- a/src/components/user/Layout/index.ts
+++ b/src/components/user/Layout/index.ts
@@ -3,6 +3,6 @@ import { getDefaultData } from './util';
export default {
name: 'sb-layout',
getDefaultData,
- edit: () => import('./edit'),
- display: () => import('./edit'),
+ edit: () => import('./edit.tsx'),
+ display: () => import('./display.tsx'),
};
diff --git a/src/components/user/Layout/style.scss b/src/components/user/Layout/style.scss
index c51aa9f..6cde76e 100644
--- a/src/components/user/Layout/style.scss
+++ b/src/components/user/Layout/style.scss
@@ -1,5 +1,6 @@
.sb-layout {
display: flex;
+ flex-basis: 100%;
&_vertical {
flex-direction: column;
@@ -8,4 +9,8 @@
&_horizontal {
flex-direction: row;
}
+
+ > * {
+ flex-basis: 100%;
+ }
}
diff --git a/src/components/user/Layout/util.ts b/src/components/user/Layout/util.ts
index 9535f4a..642dece 100644
--- a/src/components/user/Layout/util.ts
+++ b/src/components/user/Layout/util.ts
@@ -10,6 +10,7 @@ export interface LayoutData {
export interface LayoutProps extends BlockProps {
data: LayoutData;
+ eventUpdate: (b?: BlockData) => void;
}
export const getDefaultData: () => LayoutData = () => ({
diff --git a/src/components/user/Paragraph/display.tsx b/src/components/user/Paragraph/display.tsx
new file mode 100644
index 0000000..3389083
--- /dev/null
+++ b/src/components/user/Paragraph/display.tsx
@@ -0,0 +1,58 @@
+import {
+ defineComponent,
+ reactive,
+ computed,
+ ref,
+ Ref,
+ onMounted,
+ watch,
+ PropType,
+} from '@vue/composition-api';
+import {
+ model,
+ blockProps,
+ useActivation,
+} from '@components/TreeElement';
+
+import SbToolbar from '@internal/Toolbar';
+
+import {
+ getDefaultData,
+ ParagraphData,
+ ParagraphProps,
+} from './util';
+
+import './style.scss';
+
+export default defineComponent({
+ name: 'sb-paragraph-edit',
+
+ model,
+
+ props: {
+ ...blockProps,
+ data: {
+ type: (null as unknown) as PropType
,
+ default: getDefaultData,
+ },
+ eventUpdate: {
+ type: (Function as unknown) as (b?: ParagraphData) => void,
+ default: () => () => undefined,
+ },
+ eventInsertBlock: {
+ type: (Function as unknown) as (b?: ParagraphData) => void,
+ default: () => () => undefined,
+ },
+ },
+
+ setup(props: ParagraphProps, context) {
+ const classes = computed(() => ({
+ 'sb-paragraph': true,
+ [`sb-paragraph_align-${props.data.align}`]: true,
+ }));
+
+ return () => (
+ {props.data.value}
+ );
+ },
+});
diff --git a/src/components/user/Paragraph/edit.tsx b/src/components/user/Paragraph/edit.tsx
index 4364873..d54f639 100644
--- a/src/components/user/Paragraph/edit.tsx
+++ b/src/components/user/Paragraph/edit.tsx
@@ -35,6 +35,14 @@ export default defineComponent({
type: (null as unknown) as PropType,
default: getDefaultData,
},
+ eventUpdate: {
+ type: (Function as unknown) as (b?: ParagraphData) => void,
+ default: () => () => undefined,
+ },
+ eventInsertBlock: {
+ type: (Function as unknown) as (b?: ParagraphData) => void,
+ default: () => () => undefined,
+ },
},
setup(props: ParagraphProps, context) {
@@ -81,7 +89,7 @@ export default defineComponent({
}));
const setAlignment = ($event: Event) => {
- context.emit('update', { align: ($event.target as HTMLSelectElement).value });
+ props.eventUpdate({ align: ($event.target as HTMLSelectElement).value });
};
const onFocus = () => {
@@ -90,7 +98,7 @@ export default defineComponent({
const onBlur = () => {
localData.focused = false;
- context.emit('update', {
+ props.eventUpdate({
value: localData.value,
});
activate(null);
@@ -99,7 +107,7 @@ export default defineComponent({
const onKeypress = ($event: KeyboardEvent) => {
if ($event.key === 'Enter') {
const blockId = `${+(new Date())}`;
- context.emit('insert-block', {
+ props.eventInsertBlock({
blockId,
name: 'sb-paragraph',
data: getDefaultData(),
diff --git a/src/components/user/Paragraph/index.ts b/src/components/user/Paragraph/index.ts
index 712a24c..6a5c756 100644
--- a/src/components/user/Paragraph/index.ts
+++ b/src/components/user/Paragraph/index.ts
@@ -4,5 +4,5 @@ export default {
name: 'sb-paragraph',
getDefaultData,
edit: () => import('./edit'),
- display: () => import('./edit'),
+ display: () => import('./display'),
};
diff --git a/src/components/user/Paragraph/style.scss b/src/components/user/Paragraph/style.scss
index 82ad7d2..f24d14e 100644
--- a/src/components/user/Paragraph/style.scss
+++ b/src/components/user/Paragraph/style.scss
@@ -1,7 +1,9 @@
.sb-paragraph {
+ flex-basis: 100%;
+
&__input {
display: block;
- width: 100%;
+ flex-basis: 100%;
}
&_align {
diff --git a/src/directives/activation-cover.js b/src/directives/activation-cover.js
new file mode 100644
index 0000000..6d916df
--- /dev/null
+++ b/src/directives/activation-cover.js
@@ -0,0 +1,3 @@
+export default {
+
+};
diff --git a/src/main.scss b/src/main.scss
index e327f4e..1a25562 100644
--- a/src/main.scss
+++ b/src/main.scss
@@ -3,7 +3,7 @@
}
html {
- --bg: white;
+ --grey-0: white;
--grey-1-t: rgba(0, 0, 0, 0.05);
--grey-1: rgb(242, 242, 242);
--grey-2-t: rgba(0, 0, 0, 0.1);
@@ -15,4 +15,13 @@ html {
--grey-5-t: rgba(0, 0, 0, 0.7);
--grey-5: rgb(75, 75, 75);
--black: rgba(0, 0, 0, 0.9);
+
+ --bg: var(--grey-1);
+ --fg: var(--black);
+
+ --interact: #3f9cff;
+}
+
+body {
+ margin: 0;
}