small refactoring and start to support list editing
This commit is contained in:
parent
9856ad8ed1
commit
986560d284
6 changed files with 70 additions and 34 deletions
|
@ -1,6 +1,11 @@
|
|||
<template>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
|
@ -10,6 +15,30 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
|
|||
@Component
|
||||
export default class DeckCardBulletList extends Vue {
|
||||
@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>
|
||||
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
<button class="edit-close" @click.self.stop="$emit('close')" v-if="isSelection" />
|
||||
</header>
|
||||
<main>
|
||||
<component v-for="(entry, i) in card.contents"
|
||||
<component v-for="(entry, i) in card.content"
|
||||
:is="`deck-card-${entry.type}`"
|
||||
:key="`e${i}`"
|
||||
:params="entry.params"
|
||||
:editable="isSelection"
|
||||
@edit="editContent(i, $event)"
|
||||
@edit="editContentFieldParam(i, $event)"
|
||||
@replace="replaceContentField(i, $event)"
|
||||
/>
|
||||
</main>
|
||||
</section>
|
||||
|
@ -89,18 +90,25 @@ export default class DeckCard extends Vue {
|
|||
this.$emit('edit', payload)
|
||||
}
|
||||
|
||||
private editContent (index: number, event: ContentEditEvent) {
|
||||
const { param, value } = event
|
||||
const field = this.card.contents[index]
|
||||
const newContents = [...this.card.contents]
|
||||
private replaceContentField (index: number, newParams: Field['params']) {
|
||||
const newContent = [...this.card.content]
|
||||
const newField = {
|
||||
type: newContent[index].type,
|
||||
params: newParams
|
||||
}
|
||||
newContent.splice(index, 1, newField)
|
||||
|
||||
field.params[param] = value
|
||||
newContents.splice(index, 1, field)
|
||||
|
||||
const payload = { field: 'contents', value: newContents }
|
||||
const payload = { field: 'content', value: newContent }
|
||||
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 () {
|
||||
const icon = this.card.icon || this.deck.icon
|
||||
return iconPath(icon)
|
||||
|
|
|
@ -5,7 +5,6 @@ const eventHandlers: { [key: string]: () => void } = {}
|
|||
|
||||
Vue.directive('editable', (el, { value, arg }, vnode) => {
|
||||
const keypressHandler = (event: KeyboardEvent) => {
|
||||
console.log('keypress', event.code)
|
||||
// allow line break via Shift + Enter
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
event.preventDefault()
|
||||
|
|
|
@ -45,6 +45,6 @@ export function defaultCard (): Card {
|
|||
count: 1,
|
||||
tags: [],
|
||||
icon: 'robe',
|
||||
contents: []
|
||||
content: []
|
||||
}
|
||||
}
|
||||
|
|
34
src/shims.d.ts
vendored
34
src/shims.d.ts
vendored
|
@ -1,10 +1,17 @@
|
|||
interface Settings {
|
||||
color: string;
|
||||
interface Field {
|
||||
type: string;
|
||||
params: (string | number)[];
|
||||
}
|
||||
|
||||
interface StoredStuff {
|
||||
decks: Deck[];
|
||||
defaults: Settings;
|
||||
interface Card {
|
||||
id: string;
|
||||
name: string;
|
||||
count: number;
|
||||
tags: string[];
|
||||
icon: string;
|
||||
content: Field[];
|
||||
backIcon?: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
interface Deck {
|
||||
|
@ -19,18 +26,11 @@ interface Deck {
|
|||
titleFontSize?: number;
|
||||
}
|
||||
|
||||
interface Card {
|
||||
id: string;
|
||||
name: string;
|
||||
count: number;
|
||||
tags: string[];
|
||||
icon: string;
|
||||
contents: CardContent[];
|
||||
backIcon?: string;
|
||||
color?: string;
|
||||
interface Settings {
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface CardContent {
|
||||
type: string;
|
||||
params: (string | number)[];
|
||||
interface StoredStuff {
|
||||
decks: Deck[];
|
||||
defaults: Settings;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ export default class DeckView extends Vue {
|
|||
count: 1,
|
||||
tags: ['foo', 'test'],
|
||||
icon: 'robe',
|
||||
contents: [
|
||||
content: [
|
||||
{ type: 'subtitle', params: ['1st Level Enchantment'] },
|
||||
{ type: 'rule', params: ['pointing-right'] },
|
||||
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
||||
|
@ -89,7 +89,7 @@ export default class DeckView extends Vue {
|
|||
count: 1,
|
||||
tags: ['fire', 'test'],
|
||||
icon: 'robe',
|
||||
contents: [
|
||||
content: [
|
||||
{ type: 'subtitle', params: ['1st Level Evocation'] },
|
||||
{ type: 'rule', params: ['pointing-right'] },
|
||||
{ type: 'property', params: ['Casting Time', '1 Action'] },
|
||||
|
@ -109,7 +109,7 @@ export default class DeckView extends Vue {
|
|||
count: 1,
|
||||
tags: ['wand', 'test'],
|
||||
icon: 'robe',
|
||||
contents: [
|
||||
content: [
|
||||
{ type: 'subtitle', params: ['Wondrous Item'] },
|
||||
{ type: 'rule', params: ['pointing-right'] },
|
||||
{ type: 'property', params: ['Maximum charges', '7'] },
|
||||
|
@ -128,7 +128,7 @@ export default class DeckView extends Vue {
|
|||
count: 1,
|
||||
tags: ['goblin', 'test'],
|
||||
icon: 'robe',
|
||||
contents: [
|
||||
content: [
|
||||
{ type: 'subtitle', params: ['Small humanoid (goblinoid)'] },
|
||||
{ type: 'rule', params: ['pointing-right'] },
|
||||
{ type: 'property', params: ['Armor Class', '15 (leather armor)'] },
|
||||
|
|
Loading…
Add table
Reference in a new issue