183 lines
4.2 KiB
Vue
183 lines
4.2 KiB
Vue
<template>
|
|
<Card
|
|
:style="{
|
|
padding: '0.8rem 0.85rem',
|
|
border: '1.5px solid var(--color-7)',
|
|
boxShadow: 'var(--shadow-3)',
|
|
}"
|
|
>
|
|
<div class="node-header__row">
|
|
<IconButton
|
|
v-if="!isRoot"
|
|
icon="carbon:chevron-left"
|
|
variant="outline"
|
|
size="sm"
|
|
:disabled="!prevNode"
|
|
:label="
|
|
prevNode
|
|
? $t('voyage.node.prev', { title: prevNode.event.title })
|
|
: $t('voyage.node.first')
|
|
"
|
|
:style="{ flexShrink: 0 }"
|
|
@click="prevNode && $emit('goSibling', prevNode)"
|
|
/>
|
|
<div class="node-header__center">
|
|
<EditableTitle :node="node" @rename="(t) => $emit('rename', node, t)" />
|
|
<div v-if="isRoot && node.dateLabel" class="node-header__date">
|
|
<Icon
|
|
name="carbon:calendar"
|
|
size="0.85rem"
|
|
:style="{ color: 'var(--color-6)' }"
|
|
/>
|
|
{{ node.dateLabel }}
|
|
</div>
|
|
<div class="node-header__pills">
|
|
<TimePill
|
|
v-if="!isRoot"
|
|
:node="node"
|
|
@route="$emit('routeTime', node)"
|
|
/>
|
|
<PlacePill :node="node" @route="$emit('routePlace', node)" />
|
|
</div>
|
|
<div v-if="isRoot && node.lutins?.length" class="node-header__lutins">
|
|
<div class="node-header__avatars">
|
|
<Avatar
|
|
v-for="(name, i) in node.lutins.slice(0, 4)"
|
|
:key="name"
|
|
:name="name"
|
|
:size="26"
|
|
:style="{ marginLeft: i === 0 ? '0' : '-7px' }"
|
|
/>
|
|
</div>
|
|
<span class="node-header__lutins-count"
|
|
>{{ node.lutins.length }} lutins</span
|
|
>
|
|
</div>
|
|
</div>
|
|
<IconButton
|
|
v-if="!isRoot"
|
|
icon="carbon:chevron-right"
|
|
variant="outline"
|
|
size="sm"
|
|
:disabled="!nextNode"
|
|
:label="
|
|
nextNode
|
|
? $t('voyage.node.next', { title: nextNode.event.title })
|
|
: $t('voyage.node.last')
|
|
"
|
|
:style="{ flexShrink: 0 }"
|
|
@click="nextNode && $emit('goSibling', nextNode)"
|
|
/>
|
|
</div>
|
|
<div v-if="!isRoot && total > 1" class="node-header__dots">
|
|
<div class="node-header__dots-track">
|
|
<span
|
|
v-for="(_, i) in total"
|
|
:key="i"
|
|
class="node-header__dot"
|
|
:style="{
|
|
width: i === index ? '16px' : '6px',
|
|
background: i === index ? 'var(--color-5)' : 'var(--neutral-30)',
|
|
}"
|
|
/>
|
|
</div>
|
|
<span class="node-header__dots-count">{{ index + 1 }} / {{ total }}</span>
|
|
</div>
|
|
</Card>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Node } from "~/types"
|
|
|
|
const props = defineProps<{
|
|
node: Node
|
|
prevNode: Node | null
|
|
nextNode: Node | null
|
|
index: number
|
|
total: number
|
|
}>()
|
|
|
|
defineEmits<{
|
|
rename: [node: Node, title: string]
|
|
routeTime: [node: Node]
|
|
routePlace: [node: Node]
|
|
goSibling: [node: Node]
|
|
}>()
|
|
|
|
const isRoot = computed(() => props.node.root)
|
|
</script>
|
|
|
|
<style scoped>
|
|
.node-header__row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.node-header__center {
|
|
flex: 1;
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.node-header__date {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.74rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.node-header__pills {
|
|
display: flex;
|
|
gap: 6px;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.node-header__lutins {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.node-header__avatars {
|
|
display: flex;
|
|
}
|
|
|
|
.node-header__lutins-count {
|
|
font-family: var(--font-body);
|
|
font-size: 0.76rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.node-header__dots {
|
|
margin-top: var(--space-2);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.node-header__dots-track {
|
|
display: flex;
|
|
gap: var(--space-1);
|
|
}
|
|
|
|
.node-header__dot {
|
|
height: 6px;
|
|
border-radius: var(--radius-pill);
|
|
transition: width 140ms ease;
|
|
}
|
|
|
|
.node-header__dots-count {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.66rem;
|
|
color: var(--text-faint);
|
|
}
|
|
</style>
|