implements basic menu functionalities
this includes standard block elements (headers, paragraphs, lists, rulers) but not marks (bold, italic) and for sure not special elements like the stat block
This commit is contained in:
parent
c64b9a95fb
commit
5fc559abac
4 changed files with 55 additions and 16 deletions
|
@ -17,7 +17,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||
import { blocks, State } from '@/editor.ts'
|
||||
import { blocks, State } from '@/editor'
|
||||
|
||||
@Component
|
||||
export default class DeckCardEditorMenu extends Vue {
|
||||
|
@ -50,7 +50,7 @@ export default class DeckCardEditorMenu extends Vue {
|
|||
padding: .2rem 1rem;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s, visibility 0.2s;
|
||||
transition: opacity .3s .2s, visibility .3s .2s;
|
||||
background-color: var(--highlight-color);
|
||||
z-index: 2;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/>
|
||||
|
||||
<div
|
||||
:ref="content"
|
||||
ref="content"
|
||||
class="card-content"
|
||||
:contenteditable="active"
|
||||
@focus="start"
|
||||
|
@ -30,13 +30,14 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
|
|||
import DeckCardEditorMenu from '@/components/deck-card-editor-menu.vue'
|
||||
import {
|
||||
elementNameToMenuState,
|
||||
menuActionToCommand,
|
||||
getElementAndParentName,
|
||||
marks,
|
||||
blocks,
|
||||
State,
|
||||
movementKeys,
|
||||
controlSequenceKeys
|
||||
} from '@/editor.ts'
|
||||
} from '@/editor'
|
||||
|
||||
@Component({
|
||||
components: { DeckCardEditorMenu }
|
||||
|
@ -91,7 +92,13 @@ export default class DeckCardEditor extends Vue {
|
|||
|
||||
private editorAction (action: string) {
|
||||
console.log('action', action)
|
||||
// const content = this.$refs.content
|
||||
const content = this.$refs.content as HTMLElement
|
||||
content.focus()
|
||||
|
||||
const cmd = menuActionToCommand[action]
|
||||
cmd()
|
||||
|
||||
this.$nextTick(() => this.syncMenuState())
|
||||
}
|
||||
|
||||
private syncMenuState () {
|
||||
|
@ -121,6 +128,8 @@ export default class DeckCardEditor extends Vue {
|
|||
private start () {
|
||||
this.contentInFocus = true
|
||||
this.syncMenuState()
|
||||
// insert paragraphs instead of DIVs on enter
|
||||
document.execCommand('defaultParagraphSeparator', false, 'p')
|
||||
}
|
||||
|
||||
private stop () {
|
||||
|
@ -129,7 +138,7 @@ export default class DeckCardEditor extends Vue {
|
|||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.card-content p {
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
export type State = KV<boolean>
|
||||
|
||||
export const movementKeys = [
|
||||
'ArrowLeft',
|
||||
'ArrowRight',
|
||||
|
@ -37,11 +35,3 @@ export const blocks = [
|
|||
'separator',
|
||||
'statBlock'
|
||||
]
|
||||
|
||||
export function getElementAndParentName (el: Node) {
|
||||
const element = el.nodeName === '#text' ? el.parentElement : el
|
||||
return [
|
||||
element?.nodeName,
|
||||
element?.parentElement?.nodeName
|
||||
]
|
||||
}
|
40
src/editor/index.ts
Normal file
40
src/editor/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
export type State = KV<boolean>
|
||||
export {
|
||||
movementKeys,
|
||||
controlSequenceKeys,
|
||||
elementNameToMenuState,
|
||||
marks,
|
||||
blocks
|
||||
} from './constants'
|
||||
|
||||
function simpleAction (cmd: string, arg?: string): () => boolean {
|
||||
return () => {
|
||||
return document.execCommand(cmd, false, arg)
|
||||
}
|
||||
}
|
||||
|
||||
function insertHorizontalRule (): () => boolean {
|
||||
return () => {
|
||||
const hr = document.execCommand('insertHorizontalRule')
|
||||
const p = document.execCommand('formatblock', false, 'P')
|
||||
return hr && p
|
||||
}
|
||||
}
|
||||
|
||||
export const menuActionToCommand: KV<() => boolean> = {
|
||||
paragraph: simpleAction('formatblock', 'P'),
|
||||
heading1: simpleAction('formatblock', 'H1'),
|
||||
heading2: simpleAction('formatblock', 'H2'),
|
||||
heading3: simpleAction('formatblock', 'H3'),
|
||||
bulletList: simpleAction('insertUnorderedList'),
|
||||
numberedList: simpleAction('insertOrderedList'),
|
||||
separator: insertHorizontalRule()
|
||||
}
|
||||
|
||||
export function getElementAndParentName (el: Node) {
|
||||
const element = el.nodeName === '#text' ? el.parentElement : el
|
||||
return [
|
||||
element?.nodeName,
|
||||
element?.parentElement?.nodeName
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue