Improved display mode
This commit is contained in:
parent
7156fe11e0
commit
f408114fc7
11
src/App.tsx
11
src/App.tsx
|
@ -6,6 +6,8 @@ import {
|
||||||
import Schlechtenburg from '@components/Schlechtenburg';
|
import Schlechtenburg from '@components/Schlechtenburg';
|
||||||
import { Block } from './components/TreeElement';
|
import { Block } from './components/TreeElement';
|
||||||
|
|
||||||
|
import initialData from './initial-data.json';
|
||||||
|
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -13,14 +15,7 @@ export default defineComponent({
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const activeTab = ref('edit');
|
const activeTab = ref('edit');
|
||||||
const block = reactive({
|
const block = reactive(initialData) as Block;
|
||||||
name: 'sb-layout',
|
|
||||||
blockId: `${+(new Date())}`,
|
|
||||||
data: {
|
|
||||||
orientation: 'vertical',
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
}) as Block;
|
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Block,
|
Block,
|
||||||
useDynamicBlocks,
|
useDynamicBlocks,
|
||||||
useActivation,
|
useActivation,
|
||||||
|
SbMode,
|
||||||
} from '@components/TreeElement';
|
} from '@components/TreeElement';
|
||||||
|
|
||||||
import './Block.scss';
|
import './Block.scss';
|
||||||
|
@ -33,7 +34,7 @@ export default defineComponent({
|
||||||
|
|
||||||
setup(props: BlockProps, context) {
|
setup(props: BlockProps, context) {
|
||||||
const { isActive, activate } = useActivation(props.block.blockId);
|
const { isActive, activate } = useActivation(props.block.blockId);
|
||||||
const { getBlock } = useDynamicBlocks();
|
const { mode, getBlock } = useDynamicBlocks();
|
||||||
const classes = computed(() => ({
|
const classes = computed(() => ({
|
||||||
'sb-block': true,
|
'sb-block': true,
|
||||||
'sb-block_active': isActive.value,
|
'sb-block_active': isActive.value,
|
||||||
|
@ -51,6 +52,15 @@ export default defineComponent({
|
||||||
|
|
||||||
const BlockComponent = getBlock(props.block.name) as any;
|
const BlockComponent = getBlock(props.block.name) as any;
|
||||||
|
|
||||||
|
if (mode.value === SbMode.Display) {
|
||||||
|
return () => (
|
||||||
|
<BlockComponent
|
||||||
|
data={props.block.data}
|
||||||
|
block-id={props.block.blockId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return () => (<div class={classes.value}>
|
return () => (<div class={classes.value}>
|
||||||
<div class="sb-block__edit-cover"></div>
|
<div class="sb-block__edit-cover"></div>
|
||||||
<div class="sb-block__mover"></div>
|
<div class="sb-block__mover"></div>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
&__overlay {
|
&__overlay {
|
||||||
background-color: var(--grey-3-t);
|
background-color: var(--grey-3-t);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
z-index: 10;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
|
@ -1,18 +1,9 @@
|
||||||
import {
|
import { defineComponent, PropType } from '@vue/composition-api';
|
||||||
defineComponent,
|
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
Ref,
|
|
||||||
watch,
|
|
||||||
PropType,
|
|
||||||
} from '@vue/composition-api';
|
|
||||||
import {
|
import {
|
||||||
model,
|
model,
|
||||||
blockProps,
|
blockProps,
|
||||||
} from '@components/TreeElement';
|
} from '@components/TreeElement';
|
||||||
|
|
||||||
import SbToolbar from '@internal/Toolbar';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getDefaultData,
|
getDefaultData,
|
||||||
ImageData,
|
ImageData,
|
||||||
|
@ -34,60 +25,11 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props: ImageProps, context) {
|
setup(props: ImageProps) {
|
||||||
const localData = reactive({
|
return () => <img
|
||||||
src: props.data.src,
|
class="sb-image"
|
||||||
alt: props.data.alt,
|
src={props.data.src}
|
||||||
});
|
alt={props.data.alt}
|
||||||
|
/>;
|
||||||
|
|
||||||
const fileInput: Ref<null|HTMLInputElement> = ref(null);
|
|
||||||
|
|
||||||
watch(() => props.data, () => {
|
|
||||||
localData.src = props.data.src;
|
|
||||||
localData.alt = props.data.alt;
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectImage = () => {
|
|
||||||
if (fileInput.value) {
|
|
||||||
fileInput.value.click();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onImageSelect = () => {
|
|
||||||
if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {
|
|
||||||
context.emit('update', {
|
|
||||||
src: window.URL.createObjectURL(fileInput.value.files[0]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<div class="sb-image">
|
|
||||||
<SbToolbar>
|
|
||||||
Image Edit
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
ref="fileInput"
|
|
||||||
style="display: none;"
|
|
||||||
{...{
|
|
||||||
on: {
|
|
||||||
input: onImageSelect,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SbToolbar>
|
|
||||||
{localData.src
|
|
||||||
? <img src={localData.src} alt={localData.alt} />
|
|
||||||
: <button
|
|
||||||
{...{
|
|
||||||
on: {
|
|
||||||
click: selectImage,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>Select Image</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,18 +28,20 @@ export default defineComponent({
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
...blockProps,
|
...blockProps,
|
||||||
|
eventUpdate: { type: Function, default: () => {} },
|
||||||
data: {
|
data: {
|
||||||
type: (null as unknown) as PropType<ImageData>,
|
type: (null as unknown) as PropType<ImageData>,
|
||||||
default: getDefaultData,
|
default: getDefaultData,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props: ImageProps, context) {
|
setup(props: ImageProps) {
|
||||||
const localData = reactive({
|
const localData = reactive({
|
||||||
src: props.data.src,
|
src: props.data.src,
|
||||||
alt: props.data.alt,
|
alt: props.data.alt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(props);
|
||||||
|
|
||||||
const fileInput: Ref<null|HTMLInputElement> = ref(null);
|
const fileInput: Ref<null|HTMLInputElement> = ref(null);
|
||||||
|
|
||||||
|
@ -56,9 +58,15 @@ export default defineComponent({
|
||||||
|
|
||||||
const onImageSelect = () => {
|
const onImageSelect = () => {
|
||||||
if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {
|
if (fileInput.value && fileInput.value.files && fileInput.value.files.length) {
|
||||||
context.emit('update', {
|
const reader = new FileReader();
|
||||||
src: window.URL.createObjectURL(fileInput.value.files[0]),
|
reader.addEventListener('load', () => {
|
||||||
|
props.eventUpdate({
|
||||||
|
src: reader.result,
|
||||||
|
alt: props.data.alt,
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
reader.readAsDataURL(fileInput.value.files[0]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,5 @@ export default {
|
||||||
name: 'sb-image',
|
name: 'sb-image',
|
||||||
getDefaultData,
|
getDefaultData,
|
||||||
edit: () => import('./edit'),
|
edit: () => import('./edit'),
|
||||||
display: () => import('./edit'),
|
display: () => import('./display'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
.sb-image {
|
.sb-image {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { BlockProps } from '@components/TreeElement';
|
import { BlockData, BlockProps } from '@components/TreeElement';
|
||||||
|
|
||||||
export interface ImageData {
|
export interface ImageData {
|
||||||
src: string;
|
src: string;
|
||||||
|
@ -7,6 +7,7 @@ export interface ImageData {
|
||||||
|
|
||||||
export interface ImageProps extends BlockProps {
|
export interface ImageProps extends BlockProps {
|
||||||
data: ImageData;
|
data: ImageData;
|
||||||
|
eventUpdate: (b?: BlockData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDefaultData: () => ImageData = () => ({
|
export const getDefaultData: () => ImageData = () => ({
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
import {
|
import {
|
||||||
reactive,
|
|
||||||
computed,
|
computed,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
watch,
|
|
||||||
PropType,
|
PropType,
|
||||||
} from '@vue/composition-api';
|
} from '@vue/composition-api';
|
||||||
import {
|
import {
|
||||||
model,
|
model,
|
||||||
blockProps,
|
blockProps,
|
||||||
useActivation,
|
|
||||||
BlockData,
|
|
||||||
} from '@components/TreeElement';
|
} from '@components/TreeElement';
|
||||||
|
|
||||||
import SbBlock from '@internal/Block';
|
import SbBlock from '@internal/Block';
|
||||||
import SbToolbar from '@internal/Toolbar';
|
|
||||||
import SbBlockPlaceholder from '@internal/BlockPlaceholder';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LayoutData,
|
LayoutData,
|
||||||
|
@ -37,7 +31,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props: LayoutProps, context) {
|
setup(props: LayoutProps) {
|
||||||
const classes = computed(() => ({
|
const classes = computed(() => ({
|
||||||
'sb-layout': true,
|
'sb-layout': true,
|
||||||
[`sb-layout_${props.data.orientation}`]: true,
|
[`sb-layout_${props.data.orientation}`]: true,
|
||||||
|
@ -45,7 +39,7 @@ export default defineComponent({
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div class={classes.value}>
|
<div class={classes.value}>
|
||||||
{...props.data.children.map((child, index) => (
|
{...props.data.children.map((child) => (
|
||||||
<SbBlock
|
<SbBlock
|
||||||
key={child.blockId}
|
key={child.blockId}
|
||||||
block={child}
|
block={child}
|
||||||
|
|
|
@ -33,12 +33,17 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props: ParagraphProps, context) {
|
setup(props: ParagraphProps) {
|
||||||
const classes = computed(() => ({
|
const classes = computed(() => ({
|
||||||
'sb-paragraph': true,
|
'sb-paragraph': true,
|
||||||
[`sb-paragraph_align-${props.data.align}`]: true,
|
[`sb-paragraph_align-${props.data.align}`]: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return () => <p class={classes}>{props.data.value}</p>;
|
return () => <p
|
||||||
|
class={classes.value}
|
||||||
|
{...{
|
||||||
|
domProps: { innerHTML: props.data.value },
|
||||||
|
}}
|
||||||
|
></p>;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -98,6 +98,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const onFocus = () => {
|
const onFocus = () => {
|
||||||
localData.focused = true;
|
localData.focused = true;
|
||||||
|
activate();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onBlur = () => {
|
const onBlur = () => {
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&_align {
|
&_align {
|
||||||
&-left { .sb-paragraph__input { text-align: left; } }
|
&-left { &, .sb-paragraph__input { text-align: left; } }
|
||||||
&-right { .sb-paragraph__input { text-align: right; } }
|
&-right { &, .sb-paragraph__input { text-align: right; } }
|
||||||
&-center { .sb-paragraph__input { text-align: center; } }
|
&-center { &, .sb-paragraph__input { text-align: center; } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
58
src/initial-data.json
Normal file
58
src/initial-data.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -8,6 +8,7 @@
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"types": [
|
"types": [
|
||||||
|
|
Loading…
Reference in a new issue