|
|
@@ -1,18 +1,28 @@
|
|
|
<template>
|
|
|
- <component
|
|
|
- ref="element"
|
|
|
- :is="showInfo.tagName"
|
|
|
- :id="item.frontendId"
|
|
|
- @compositionstart.stop="handleCompositionStart"
|
|
|
- @compositionend.stop="handleCompositionEnd"
|
|
|
- @input.stop="handleInput"
|
|
|
- @keydown.stop="handleKeyDown"
|
|
|
- contenteditable
|
|
|
- v-html="showInfo.content"
|
|
|
- :class="showInfo.className"
|
|
|
- :placeholder="showInfo.placeholder"
|
|
|
+ <div
|
|
|
+ class="reset-div item-container"
|
|
|
+ @mouseenter="handleMouseEnter"
|
|
|
+ @mouseleave="handleMouseLeave"
|
|
|
>
|
|
|
- </component>
|
|
|
+ <div
|
|
|
+ class="item-menu"
|
|
|
+ :class="className"
|
|
|
+ >{{iconfontMap[type]}}</div>
|
|
|
+ <component
|
|
|
+ ref="element"
|
|
|
+ :is="showInfo.tagName"
|
|
|
+ :id="item.frontendId"
|
|
|
+ @compositionstart.stop="handleCompositionStart"
|
|
|
+ @compositionend.stop="handleCompositionEnd"
|
|
|
+ @input.stop="handleInput"
|
|
|
+ @keydown.stop="handleKeyDown"
|
|
|
+ contenteditable
|
|
|
+ v-html="showInfo.content"
|
|
|
+ :class="showInfo.className"
|
|
|
+ :placeholder="showInfo.placeholder"
|
|
|
+ >
|
|
|
+ </component>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
@@ -22,11 +32,13 @@ import {
|
|
|
DELETE_ITEM,
|
|
|
SET_FOCUS_AFTER,
|
|
|
SET_FOCUS_BEFORE,
|
|
|
- SET_FOCUS
|
|
|
+ SET_FOCUS, SET_HOVER
|
|
|
} from '@/store/types/editor-types'
|
|
|
import defaultPlaceholder from '@/utils/default-placeholder'
|
|
|
import defaultMarkdownFragment from '@/utils/default-markdown-fragment'
|
|
|
import { matchType, generateShowInfo } from '@/utils/item-common'
|
|
|
+import iconfontMap from '@/utils/iconfont-map'
|
|
|
+import { mapState } from 'vuex'
|
|
|
|
|
|
export default {
|
|
|
name: 'editable-item',
|
|
|
@@ -35,7 +47,8 @@ export default {
|
|
|
return {
|
|
|
isCompositionStarted: false,
|
|
|
range: null,
|
|
|
- type: 'div'
|
|
|
+ type: 'div',
|
|
|
+ iconfontMap: iconfontMap
|
|
|
}
|
|
|
},
|
|
|
mounted () {
|
|
|
@@ -45,8 +58,17 @@ export default {
|
|
|
this.type = this.matchType(this.item.content)
|
|
|
},
|
|
|
computed: {
|
|
|
+ ...mapState({
|
|
|
+ hover: state => state.editor.hover
|
|
|
+ }),
|
|
|
showInfo () {
|
|
|
return generateShowInfo(this.type, this.item)
|
|
|
+ },
|
|
|
+ className() {
|
|
|
+ return {
|
|
|
+ 'icon-hover': this.hover === this.item.frontendId,
|
|
|
+ 'heading': this.type.match(/h[0-6]/)
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
@@ -170,38 +192,52 @@ export default {
|
|
|
cb()
|
|
|
}
|
|
|
})
|
|
|
+ },
|
|
|
+ handleMouseEnter () {
|
|
|
+ this.$store.commit(SET_HOVER, { frontendId: this.item.frontendId })
|
|
|
+ },
|
|
|
+ handleMouseLeave () {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-@import '~@/common/slide/item.scss';
|
|
|
+@import '~@/common/slide/editing-item.scss';
|
|
|
|
|
|
-* [contenteditable] {
|
|
|
- outline: none;
|
|
|
- width: 100%;
|
|
|
+.reset-div {
|
|
|
+ padding: unset;
|
|
|
+ line-height: unset;
|
|
|
+}
|
|
|
|
|
|
+.item-menu {
|
|
|
+ opacity: 0;
|
|
|
+ cursor: pointer;
|
|
|
+ font-family: 'iconfont', sans-serif;
|
|
|
+ position: absolute;
|
|
|
+ transform: translateX(-32px);
|
|
|
+ color: #9aaaba;
|
|
|
+ font-size: .9em;
|
|
|
+ transition: 0.2s;
|
|
|
&:hover {
|
|
|
- background: #fafcfe;
|
|
|
+ color: #6a7a8a;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- &:focus {
|
|
|
- background: #f9fafc;
|
|
|
- }
|
|
|
+.icon-hover {
|
|
|
+ opacity: 1;
|
|
|
+}
|
|
|
|
|
|
- &:empty:before {
|
|
|
- content: attr(placeholder);
|
|
|
- color: #bbb;
|
|
|
- }
|
|
|
+.heading {
|
|
|
+ transform: translateX(-32px) scaleY(.9);
|
|
|
}
|
|
|
|
|
|
-.slideBreak {
|
|
|
- color: lightblue;
|
|
|
+.item-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
|
|
|
- &:empty:before {
|
|
|
- content: attr(placeholder);
|
|
|
- color: lightblue;
|
|
|
+ & > * {
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
}
|
|
|
</style>
|