prepare for editable cards
This commit is contained in:
parent
747d6b8471
commit
773ce67d70
4 changed files with 65 additions and 2 deletions
|
@ -123,3 +123,8 @@ button.edit-close {
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
button.edit-pencil {
|
||||||
|
background: transparent url(./zondicons/edit-pencil.svg) center no-repeat;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<h3>{{ params[0] }}</h3>
|
<h3 :contenteditable="editable"
|
||||||
|
@keypress.enter.prevent="$emit('edit', { param: 0, value: $event.target.innerText })">
|
||||||
|
{{ params[0] }}
|
||||||
|
</h3>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -8,6 +11,7 @@ import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
@Component
|
@Component
|
||||||
export default class DeckCardSubtitle extends Vue {
|
export default class DeckCardSubtitle extends Vue {
|
||||||
@Prop() public readonly params!: string[]
|
@Prop() public readonly params!: string[]
|
||||||
|
@Prop() public readonly editable!: boolean
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
@click="clickUnlessSelected">
|
@click="clickUnlessSelected">
|
||||||
<section name="card-front" class="card-front">
|
<section name="card-front" class="card-front">
|
||||||
<header>
|
<header>
|
||||||
<h2>{{ card.name }}</h2>
|
<h2 :contenteditable="isSelection"
|
||||||
|
@keypress.enter.prevent="editField('name', $event)">
|
||||||
|
{{ card.name }}
|
||||||
|
</h2>
|
||||||
<img :src="icon" />
|
<img :src="icon" />
|
||||||
<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>
|
||||||
|
@ -16,6 +19,8 @@
|
||||||
:is="`deck-card-${entry.type}`"
|
:is="`deck-card-${entry.type}`"
|
||||||
:key="`e${i}`"
|
:key="`e${i}`"
|
||||||
:params="entry.params"
|
:params="entry.params"
|
||||||
|
:editable="isSelection"
|
||||||
|
@edit="editContent(i, $event)"
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
|
@ -44,6 +49,11 @@ import DeckCardBulletList from './deck-card-bullet-list.vue'
|
||||||
import DeckCardBoxes from './deck-card-boxes.vue'
|
import DeckCardBoxes from './deck-card-boxes.vue'
|
||||||
import DeckCardDndstats from './deck-card-dndstats.vue'
|
import DeckCardDndstats from './deck-card-dndstats.vue'
|
||||||
|
|
||||||
|
interface ContentEditEvent {
|
||||||
|
param: number;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
DeckCardSubtitle,
|
DeckCardSubtitle,
|
||||||
|
@ -64,11 +74,33 @@ export default class DeckCard extends Vue {
|
||||||
@Prop() public readonly deck!: Deck
|
@Prop() public readonly deck!: Deck
|
||||||
@Prop() public readonly isSelection!: boolean
|
@Prop() public readonly isSelection!: boolean
|
||||||
|
|
||||||
|
private editHeadline = false;
|
||||||
|
private editFieldIndex: number | null = null;
|
||||||
|
|
||||||
private clickUnlessSelected () {
|
private clickUnlessSelected () {
|
||||||
if (this.isSelection) return
|
if (this.isSelection) return
|
||||||
this.$emit('click')
|
this.$emit('click')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private editField (field: string, event: Event) {
|
||||||
|
if (event.target === null) return
|
||||||
|
const target = event.target as HTMLElement
|
||||||
|
const payload = { field, value: target.innerText }
|
||||||
|
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]
|
||||||
|
|
||||||
|
field.params[param] = value
|
||||||
|
newContents.splice(index, 1, field)
|
||||||
|
|
||||||
|
const payload = { field: 'contents', value: newContents }
|
||||||
|
this.$emit('edit', payload)
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -219,4 +251,21 @@ export default class DeckCard extends Vue {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
margin-top: -3rem;
|
margin-top: -3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[contenteditable="true"] {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
[contenteditable="true"]::after {
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-bottom: 1px dotted white;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
[contenteditable="true"]:focus::after {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
:is-selection="card === selection"
|
:is-selection="card === selection"
|
||||||
@click="selection = card"
|
@click="selection = card"
|
||||||
@close="selection = null"
|
@close="selection = null"
|
||||||
|
@edit="editCard(card, $event.field, $event.value)"
|
||||||
/>
|
/>
|
||||||
<deck-cover @click="newCard" />
|
<deck-cover @click="newCard" />
|
||||||
</section>
|
</section>
|
||||||
|
@ -170,6 +171,10 @@ export default class DeckView extends Vue {
|
||||||
this.deck.cards.push(newCard)
|
this.deck.cards.push(newCard)
|
||||||
this.selection = newCard
|
this.selection = newCard
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private editCard<Card, K extends keyof Card> (card: Card, field: K, value: Card[K]) {
|
||||||
|
card[field] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue