diff options
| -rw-r--r-- | src/App.vue | 44 | ||||
| -rw-r--r-- | src/components/TimeLine.vue | 26 | ||||
| -rw-r--r-- | src/components/icon/MinusIcon.vue | 6 | ||||
| -rw-r--r-- | src/components/icon/PlusIcon.vue | 7 |
4 files changed, 72 insertions, 11 deletions
diff --git a/src/App.vue b/src/App.vue index 73d74aa..cfd9084 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,26 +5,40 @@ <h1 class="my-auto ml-2 text-4xl">Histplorer</h1> <div class="mx-auto"/> <!-- Spacer --> <!-- Icons --> - <icon-button :size="45" class="text-stone-50 bg-yellow-600"> - <help-icon/> + <icon-button :size="45" class="text-stone-50 bg-yellow-600" @click="onTimelineAdd" title="Add a timeline"> + <plus-icon/> </icon-button> <icon-button :size="45" class="text-stone-50 bg-yellow-600"> <settings-icon/> </icon-button> + <icon-button :size="45" class="text-stone-50 bg-yellow-600"> + <help-icon/> + </icon-button> </div> <!-- Content area --> - <div class="grow min-h-0 bg-stone-800" ref="contentAreaRef"> - <time-line :width="contentWidth" :height="contentHeight" :vert="contentHeight > contentWidth"/> + <div class="grow min-h-0 bg-stone-800 relative" ref="contentAreaRef"> + <time-line v-for="(data, idx) in timelineData" :key="data" + :style="{ + position: 'absolute', + top: (vert ? 0 : idx * contentHeight / timelineData.length) + 'px', + left: (vert ? idx * contentWidth / timelineData.length : 0) + 'px', + outline: 'black solid 1px', + }" + :width="vert ? contentWidth / timelineData.length : contentWidth" + :height="vert ? contentHeight : contentHeight / timelineData.length" + :vert="vert" + @close="onTimelineClose(idx)"/> </div> </div> </template> <script setup lang="ts"> -import {ref, onMounted, onUnmounted} from 'vue'; +import {ref, computed, onMounted, onUnmounted} from 'vue'; // Components import TimeLine from './components/TimeLine.vue'; import IconButton from './components/IconButton.vue'; // Icons +import PlusIcon from './components/icon/PlusIcon.vue'; import SettingsIcon from './components/icon/SettingsIcon.vue'; import HelpIcon from './components/icon/HelpIcon.vue'; @@ -41,6 +55,25 @@ function updateAreaDims(){ } onMounted(updateAreaDims) +// For multiple timelines +const vert = computed(() => contentHeight.value > contentWidth.value); +const timelineData = ref([{}]); +function onTimelineAdd(){ + if (vert.value && contentWidth.value / (timelineData.value.length + 1) < 150 || + !vert.value && contentHeight.value / (timelineData.value.length + 1) < 150){ + console.log('Reached timeline min size'); + return; + } + timelineData.value.push({}); +} +function onTimelineClose(idx: number){ + if (timelineData.value.length == 1){ + console.log('Ignored close for last timeline') + return; + } + timelineData.value.splice(idx, 1); +} + // For resize handling let lastResizeHdlrTime = 0; // Used to throttle resize handling let afterResizeHdlr = 0; // Used to trigger handler after ending a run of resize events @@ -65,5 +98,4 @@ async function onResize(){ } onMounted(() => window.addEventListener('resize', onResize)); onUnmounted(() => window.removeEventListener('resize', onResize)); - </script> diff --git a/src/components/TimeLine.vue b/src/components/TimeLine.vue index 58e2fbc..187d915 100644 --- a/src/components/TimeLine.vue +++ b/src/components/TimeLine.vue @@ -1,13 +1,14 @@ <template> -<div class="touch-none" :width="width" :height="height" +<div class="touch-none relative" + :style="{minWidth: width + 'px', maxWidth: width + 'px', maxHeight: height + 'px', minHeight: height + 'px'}" @wheel.exact.prevent="onWheel" @wheel.shift.exact.prevent="onShiftWheel" @pointerdown.prevent="onPointerDown" @pointermove.prevent="onPointerMove" @pointerup.prevent="onPointerUp" @pointercancel.prevent="onPointerUp" @pointerout.prevent="onPointerUp" @pointerleave.prevent="onPointerUp" ref="rootRef"> - <svg :viewBox="`0 0 ${width} ${height}`"> + <svg :viewBox="`0 0 ${width} ${height}`" width="100%" height="100%"> <line stroke="yellow" stroke-width="2px" - :x1="vert2 ? '50%' : 0" :y1="vert2 ? 0 : '50%'" - :x2="vert2 ? '50%' : '100%'" :y2="vert2 ? '100%' : '50%'"/> + :x1="vert2 ? width/2 : 0" :y1="vert2 ? 0 : height/2" + :x2="vert2 ? width/2 : width" :y2="vert2 ? height : height/2"/> <template v-for="n in ticks" :key="n"> <line v-if="n == MIN_DATE || n == MAX_DATE" :x1="vert2 ? -END_TICK_SZ : 0" :y1="vert2 ? 0 : -END_TICK_SZ" @@ -24,21 +25,31 @@ {{n}} </text> </svg> + <!-- Icons --> + <icon-button :size="30" class="absolute bottom-2 right-2 text-stone-50 bg-yellow-600" + @click="onClose" title="Remove timeline"> + <minus-icon/> + </icon-button> </div> </template> <script setup lang="ts"> import {ref, onMounted, computed, watch, nextTick} from 'vue'; +// Components +import IconButton from './IconButton.vue'; +// Icons +import MinusIcon from './icon/MinusIcon.vue'; // Refs const rootRef = ref(null as HTMLElement | null); -// Props +// Props + events const props = defineProps({ width: {type: Number, required: true}, height: {type: Number, required: true}, vert: {type: Boolean, default: false}, }); +const emit = defineEmits(['close']); // Vars const MIN_DATE = -1000; // Lowest date that gets marked @@ -336,6 +347,11 @@ function onShiftWheel(evt: WheelEvent){ } } +// For button handling +function onClose(){ + emit('close'); +} + // Styles function tickStyles(tick: number){ let offset = (tick - startDate.value) / (endDate.value - startDate.value) * availLen.value; diff --git a/src/components/icon/MinusIcon.vue b/src/components/icon/MinusIcon.vue new file mode 100644 index 0000000..d316073 --- /dev/null +++ b/src/components/icon/MinusIcon.vue @@ -0,0 +1,6 @@ +<template> +<svg viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> + <line x1="5" y1="12" x2="19" y2="12"/> +</svg> +</template> diff --git a/src/components/icon/PlusIcon.vue b/src/components/icon/PlusIcon.vue new file mode 100644 index 0000000..e06ba79 --- /dev/null +++ b/src/components/icon/PlusIcon.vue @@ -0,0 +1,7 @@ +<template> +<svg viewBox="0 0 24 24" + fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> + <line x1="12" y1="5" x2="12" y2="19"/> + <line x1="5" y1="12" x2="19" y2="12"/> +</svg> +</template> |
