small refactoring and start to support list editing

tiptap
koehr 5 years ago
parent 9856ad8ed1
commit 986560d284

@ -1,6 +1,11 @@
<template> <template>
<ul> <ul>
<li :key="param" v-for="param in params">{{ param }}</li> <li v-for="(param, i) in params"
:key="`param${i}`"
v-editable:[i]="editable"
@keydown="handleKey(i, $event)">
{{ param }}
</li>
</ul> </ul>
</template> </template>
@ -10,6 +15,30 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
@Component @Component
export default class DeckCardBulletList extends Vue { export default class DeckCardBulletList extends Vue {
@Prop() public readonly params!: string[] @Prop() public readonly params!: string[]
@Prop() public readonly editable!: boolean
private addEntry (index: number) {
const newParams = [...this.params]
newParams.splice(index + 1, 0, '')
this.$emit('replace', newParams)
}
private removeEntry (index: number) {
const newParams = [...this.params]
newParams.splice(index, 1)
this.$emit('replace', newParams)
}
private handleKey (index: number, event: KeyboardEvent) {
const { key, shiftKey } = event
if (key === 'Enter' && shiftKey) {
event.preventDefault()
this.addEntry(index)
} else if (key === 'Backspace') {
const text = (event.target as HTMLElement).innerText
if (text.trim() === '') this.removeEntry(index)
}
}
} }
</script> </script>

@ -15,12 +15,13 @@
<button class="edit-close" @click.self.stop="$emit('close')" v-if="isSelection" /> <button class="edit-close" @click.self.stop="$emit('close')" v-if="isSelection" />
</header> </header>
<main> <main>
<component v-for="(entry, i) in card.contents" <component v-for="(entry, i) in card.content"
:is="`deck-card-${entry.type}`" :is="`deck-card-${entry.type}`"
:key="`e${i}`" :key="`e${i}`"
:params="entry.params" :params="entry.params"
:editable="isSelection" :editable="isSelection"
@edit="editContent(i, $event)" @edit="editContentFieldParam(i, $event)"
@replace="replaceContentField(i, $event)"
/> />
</main> </main>
</section> </section>
@ -89,18 +90,25 @@ export default class DeckCard extends Vue {
this.$emit('edit', payload) this.$emit('edit', payload)
} }
private editContent (index: number, event: ContentEditEvent) { private replaceContentField (index: number, newParams: Field['params']) {
const { param, value } = event const newContent = [...this.card.content]
const field = this.card.contents[index] const newField = {
const newContents = [...this.card.contents] type: newContent[index].type,
params: newParams
field.params[param] = value }
newContents.splice(index, 1, field) newContent.splice(index, 1, newField)
const payload = { field: 'contents', value: newContents } const payload = { field: 'content', value: newContent }
this.$emit('edit', payload) this.$emit('edit', payload)
} }
private editContentFieldParam (index: number, event: ContentEditEvent) {
const { param, value } = event
const params = [...this.card.content[index].params]
params[param] = value
this.replaceContentField(index, params)
}
private get icon () { private get icon () {
const icon = this.card.icon || this.deck.icon const icon = this.card.icon || this.deck.icon
return iconPath(icon) return iconPath(icon)

@ -5,7 +5,6 @@ const eventHandlers: { [key: string]: () => void } = {}
Vue.directive('editable', (el, { value, arg }, vnode) => { Vue.directive('editable', (el, { value, arg }, vnode) => {
const keypressHandler = (event: KeyboardEvent) => { const keypressHandler = (event: KeyboardEvent) => {
console.log('keypress', event.code)
// allow line break via Shift + Enter // allow line break via Shift + Enter
if (event.keyCode === 13 && !event.shiftKey) { if (event.keyCode === 13 && !event.shiftKey) {
event.preventDefault() event.preventDefault()

@ -45,6 +45,6 @@ export function defaultCard (): Card {
count: 1, count: 1,
tags: [], tags: [],
icon: 'robe', icon: 'robe',
contents: [] content: []
} }
} }

34
src/shims.d.ts vendored

@ -1,10 +1,17 @@
interface Settings { interface Field {
color: string; type: string;
params: (string | number)[];
} }
interface StoredStuff { interface Card {
decks: Deck[]; id: string;
defaults: Settings; name: string;
count: number;
tags: string[];
icon: string;
content: Field[];
backIcon?: string;
color?: string;
} }
interface Deck { interface Deck {
@ -19,18 +26,11 @@ interface Deck {
titleFontSize?: number; titleFontSize?: number;
} }
interface Card { interface Settings {
id: string; color: string;
name: string;
count: number;
tags: string[];
icon: string;
contents: CardContent[];
backIcon?: string;
color?: string;
} }
interface CardContent { interface StoredStuff {
type: string; decks: Deck[];
params: (string | number)[]; defaults: Settings;
} }

@ -70,7 +70,7 @@ export default class DeckView extends Vue {
count: 1, count: 1,
tags: ['foo', 'test'], tags: ['foo', 'test'],
icon: 'robe', icon: 'robe',
contents: [ content: [
{ type: 'subtitle', params: ['1st Level Enchantment'] }, { type: 'subtitle', params: ['1st Level Enchantment'] },
{ type: 'rule', params: ['pointing-right'] }, { type: 'rule', params: ['pointing-right'] },
{ type: 'property', params: ['Casting Time', '1 Action'] }, { type: 'property', params: ['Casting Time', '1 Action'] },
@ -89,7 +89,7 @@ export default class DeckView extends Vue {
count: 1, count: 1,
tags: ['fire', 'test'], tags: ['fire', 'test'],
icon: 'robe', icon: 'robe',
contents: [ content: [
{ type: 'subtitle', params: ['1st Level Evocation'] }, { type: 'subtitle', params: ['1st Level Evocation'] },
{ type: 'rule', params: ['pointing-right'] }, { type: 'rule', params: ['pointing-right'] },
{ type: 'property', params: ['Casting Time', '1 Action'] }, { type: 'property', params: ['Casting Time', '1 Action'] },
@ -109,7 +109,7 @@ export default class DeckView extends Vue {
count: 1, count: 1,
tags: ['wand', 'test'], tags: ['wand', 'test'],
icon: 'robe', icon: 'robe',
contents: [ content: [
{ type: 'subtitle', params: ['Wondrous Item'] }, { type: 'subtitle', params: ['Wondrous Item'] },
{ type: 'rule', params: ['pointing-right'] }, { type: 'rule', params: ['pointing-right'] },
{ type: 'property', params: ['Maximum charges', '7'] }, { type: 'property', params: ['Maximum charges', '7'] },
@ -128,7 +128,7 @@ export default class DeckView extends Vue {
count: 1, count: 1,
tags: ['goblin', 'test'], tags: ['goblin', 'test'],
icon: 'robe', icon: 'robe',
contents: [ content: [
{ type: 'subtitle', params: ['Small humanoid (goblinoid)'] }, { type: 'subtitle', params: ['Small humanoid (goblinoid)'] },
{ type: 'rule', params: ['pointing-right'] }, { type: 'rule', params: ['pointing-right'] },
{ type: 'property', params: ['Armor Class', '15 (leather armor)'] }, { type: 'property', params: ['Armor Class', '15 (leather armor)'] },

Loading…
Cancel
Save