Stackedit/src/components/Layout.vue
2017-07-23 19:42:08 +01:00

166 lines
4.8 KiB
Vue

<template>
<div class="layout">
<div class="layout__panel layout__panel--inner-1" :style="{ top: inner1Y + 'px', height: inner1Height + 'px' }">
<div class="layout__panel layout__panel--inner-2" :style="{ height: inner2Height + 'px' }">
<div class="layout__panel layout__panel--inner-3" :style="{ left: inner3X + 'px', width: inner3Width + 'px' }">
<div class="layout__panel layout__panel--button-bar">
<button-bar></button-bar>
</div>
<div class="layout__panel layout__panel--preview" v-show="showSidePreview || !showEditor" :style="{ width: previewWidth + 'px', 'font-size': fontSize + 'px' }">
<preview></preview>
</div>
</div>
<div class="layout__panel layout__panel--editor" v-show="showEditor" :style="{ width: editorWidth + 'px', 'font-size': fontSize + 'px' }">
<editor></editor>
</div>
</div>
<div class="layout__panel layout__panel--status-bar" :style="{ top: statusBarY + 'px' }">
<status-bar></status-bar>
</div>
</div>
<div class="layout__panel layout__panel--navigation-bar" :style="{ top: navigationBarY + 'px' }">
<navigation-bar></navigation-bar>
</div>
<div class="layout__panel layout__panel--side-bar" :style="{ left: sideBarX + 'px' }">
<side-bar></side-bar>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
import NavigationBar from './NavigationBar';
import SideBar from './SideBar';
import ButtonBar from './ButtonBar';
import StatusBar from './StatusBar';
import Editor from './Editor';
import Preview from './Preview';
import editorSvc from '../services/editorSvc';
import constants from '../services/constants';
export default {
components: {
NavigationBar,
SideBar,
ButtonBar,
StatusBar,
Editor,
Preview,
},
computed: mapState('layout', {
showEditor: 'showEditor',
showSidePreview: 'showSidePreview',
fontSize: 'fontSize',
inner1Y: 'inner1Y',
inner1Height: 'inner1Height',
inner2Height: 'inner2Height',
inner3X: 'inner3X',
inner3Width: 'inner3Width',
navigationBarY: 'navigationBarY',
sideBarX: 'sideBarX',
statusBarY: 'statusBarY',
previewWidth: 'previewWidth',
editorWidth: 'editorWidth',
}),
methods: {
...mapActions('layout', [
'updateStyle',
]),
saveSelection: () => editorSvc.saveSelection(true),
},
created() {
this.updateStyle();
window.addEventListener('resize', this.updateStyle);
window.addEventListener('keyup', this.saveSelection);
window.addEventListener('mouseup', this.saveSelection);
window.addEventListener('contextmenu', this.saveSelection);
},
mounted() {
const editorElt = this.$el.querySelector('.editor__inner');
const previewElt = this.$el.querySelector('.preview__inner');
const tocElt = this.$el.querySelector('.toc__inner');
editorSvc.init(editorElt, previewElt, tocElt);
// TOC click behaviour
let isMousedown;
function onClick(e) {
if (!isMousedown) {
return;
}
e.preventDefault();
const y = e.clientY - tocElt.getBoundingClientRect().top;
this.$store.state.sectionDescList.some((sectionDesc) => {
if (y >= sectionDesc.tocDimension.endOffset) {
return false;
}
const posInSection = (y - sectionDesc.tocDimension.startOffset)
/ (sectionDesc.tocDimension.height || 1);
const editorScrollTop = sectionDesc.editorDimension.startOffset
+ (sectionDesc.editorDimension.height * posInSection);
editorElt.parentNode.scrollTop = editorScrollTop - constants.scrollOffset;
const previewScrollTop = sectionDesc.previewDimension.startOffset
+ (sectionDesc.previewDimension.height * posInSection);
previewElt.parentNode.scrollTop = previewScrollTop - constants.scrollOffset;
return true;
});
}
tocElt.addEventListener('mouseup', () => {
isMousedown = false;
});
tocElt.addEventListener('mouseleave', () => {
isMousedown = false;
});
tocElt.addEventListener('mousedown', (e) => {
isMousedown = e.which === 1;
onClick(e);
});
tocElt.addEventListener('mousemove', (e) => {
onClick(e);
});
},
destroyed() {
window.removeEventListener('resize', this.updateStyle);
},
};
</script>
<style lang="scss">
.layout__panel {
position: absolute;
width: 100%;
height: 100%;
}
.layout__panel--inner-1 {
right: 0;
}
.layout__panel--button-bar {
/* buttonBarWidth */
width: 30px;
}
.layout__panel--preview {
/* buttonBarWidth */
left: 30px;
}
.layout__panel--status-bar {
/* statusBarHeight */
height: 20px;
background-color: #007acc;
}
.layout__panel--side-bar {
/* sideBarWidth */
width: 280px;
}
.layout__panel--navigation-bar {
/* navigationBarHeight */
height: 44px;
}
</style>