Stackedit/src/components/NavigationBar.vue
2017-07-25 19:20:52 +01:00

203 lines
6.1 KiB
Vue

<template>
<div class="navigation-bar" v-bind:class="{'navigation-bar--editor': showEditor}">
<div class="navigation-bar__inner navigation-bar__inner--right">
<div class="navigation-bar__title navigation-bar__title--text text-input" v-bind:style="{maxWidth: titleMaxWidth + 'px'}"></div>
<input class="navigation-bar__title navigation-bar__title--input text-input" v-bind:class="{'navigation-bar__title--focused': titleFocused, 'navigation-bar__title--scrolling': titleScrolling}" v-bind:style="{maxWidth: titleMaxWidth + 'px'}" @focus="editTitle(true)" @blur="editTitle(false)" @keyup.enter="submitTitle()" @keyup.esc="submitTitle(true)" v-model.lazy.trim="title">
</div>
<div class="navigation-bar__inner navigation-bar__inner--left">
<button class="navigation-bar__button button" @click="pagedownClick('bold')">
<icon-format-bold></icon-format-bold>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('italic')">
<icon-format-italic></icon-format-italic>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('strikethrough')">
<icon-format-strikethrough></icon-format-strikethrough>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('heading')">
<icon-format-size></icon-format-size>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('ulist')">
<icon-format-list-bulleted></icon-format-list-bulleted>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('olist')">
<icon-format-list-numbers></icon-format-list-numbers>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('table')">
<icon-table></icon-table>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('quote')">
<icon-format-quote-close></icon-format-quote-close>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('code')">
<icon-code-braces></icon-code-braces>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('link')">
<icon-link-variant></icon-link-variant>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('image')">
<icon-file-image></icon-file-image>
</button>
<button class="navigation-bar__button button" @click="pagedownClick('hr')">
<icon-format-horizontal-rule></icon-format-horizontal-rule>
</button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import editorSvc from '../services/editorSvc';
import animationSvc from '../services/animationSvc';
export default {
data: () => ({
titleFocused: false,
titleHover: false,
}),
computed: {
...mapState('layout', {
showEditor: 'showEditor',
titleMaxWidth: 'titleMaxWidth',
}),
title: {
get() {
return this.$store.state.files.currentFile.name;
},
set(value) {
this.$store.commit('files/setCurrentFileName', value);
},
},
titleScrolling() {
const result = this.titleHover && !this.titleFocused;
if (this.titleInputElt) {
if (result) {
const scrollLeft = this.titleInputElt.scrollWidth - this.titleInputElt.offsetWidth;
animationSvc.animate(this.titleInputElt)
.scrollLeft(scrollLeft)
.duration(scrollLeft * 10)
.easing('inOut')
.start();
} else {
animationSvc.animate(this.titleInputElt)
.scrollLeft(0)
.start();
}
}
return result;
},
},
methods: {
pagedownClick(name) {
editorSvc.pagedownEditor.uiManager.doClick(name);
},
editTitle(toggle) {
this.titleFocused = toggle;
if (toggle) {
this.titleInputElt.setSelectionRange(0, this.titleInputElt.value.length);
}
},
submitTitle(reset) {
if (reset) {
this.titleInputElt.value = '';
}
this.titleInputElt.blur();
},
},
mounted() {
this.titleInputElt = this.$el.querySelector('.navigation-bar__title--input');
const titleTextElt = this.$el.querySelector('.navigation-bar__title--text');
const adjustWidth = () => {
titleTextElt.textContent = this.titleInputElt.value;
const width = titleTextElt.getBoundingClientRect().width + 1; // 1px for the caret
this.titleInputElt.style.width = `${width}px`;
};
adjustWidth();
this.titleInputElt.addEventListener('keyup', adjustWidth);
this.titleInputElt.addEventListener('input', adjustWidth);
this.titleInputElt.addEventListener('mouseenter', () => {
this.titleHover = true;
});
this.titleInputElt.addEventListener('mouseleave', () => {
this.titleHover = false;
});
},
};
</script>
<style lang="scss">
.navigation-bar {
position: absolute;
width: 100%;
height: 100%;
background-color: #2c2c2c;
padding: 4px 15px 0;
overflow: hidden;
}
.navigation-bar__inner--right {
float: right;
}
$navbar-button-color: rgba(255, 255, 255, 0.67);
$navbar-button-hover-background: #484848;
.navigation-bar__button {
display: inline-block;
width: 34px;
padding: 6px 5px;
}
.navigation-bar__title,
.navigation-bar__button {
display: inline-block;
color: $navbar-button-color;
background-color: transparent;
font-weight: 400;
}
.navigation-bar__title--input,
.navigation-bar__button {
&:active,
&:focus,
&:hover {
color: #fff;
background-color: $navbar-button-hover-background;
}
}
.navigation-bar__title--text {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.navigation-bar__title--input,
.navigation-bar__inner--left {
display: none;
}
.navigation-bar--editor {
.navigation-bar__title--text {
position: absolute;
left: -9999px;
width: auto;
}
.navigation-bar__title--input,
.navigation-bar__inner--left {
display: block;
}
}
.navigation-bar__title--input {
cursor: pointer;
&.navigation-bar__title--focused {
cursor: text;
}
}
</style>