aboutsummaryrefslogtreecommitdiff
path: root/src/components/AncestryBar.vue
diff options
context:
space:
mode:
authorTerry Truong <terry06890@gmail.com>2022-03-28 11:49:12 +1100
committerTerry Truong <terry06890@gmail.com>2022-03-28 11:49:12 +1100
commit34e34b9620d88b5d76b87a4bbcd473c2fc6002a9 (patch)
tree03c49e4473f52172682a3d00498a4250df82eb1a /src/components/AncestryBar.vue
parentb82d3a24b2487454397535c6fefda250d4ff6114 (diff)
Rename Settings to SettingsPane, and ParentBar to AncestryBarcore-widgets
Diffstat (limited to 'src/components/AncestryBar.vue')
-rw-r--r--src/components/AncestryBar.vue74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/components/AncestryBar.vue b/src/components/AncestryBar.vue
new file mode 100644
index 0000000..2e0d5d0
--- /dev/null
+++ b/src/components/AncestryBar.vue
@@ -0,0 +1,74 @@
+<script lang="ts">
+import {defineComponent, PropType} from 'vue';
+import {LayoutNode} from '../lib';
+import TileImg from './TileImg.vue'
+
+export default defineComponent({
+ props: {
+ pos: {type: Array as unknown as PropType<[number,number]>, required: true},
+ dims: {type: Array as unknown as PropType<[number,number]>, required: true},
+ nodes: {type: Array as PropType<LayoutNode[]>, required: true},
+ options: {type: Object, required: true},
+ },
+ data(){
+ return {
+ tileMargin: 5, //px (gap between detached-ancestor tiles)
+ scrollBarOffset: 10, //px (gap for scrollbar, used to prevent overlap with tiles)
+ };
+ },
+ computed: {
+ wideArea(){
+ return this.dims[0] >= this.dims[1];
+ },
+ tileSz(){
+ return (this.wideArea ? this.dims[1] : this.dims[0]) - (this.tileMargin * 2) - this.scrollBarOffset;
+ },
+ hasOverflow(){
+ let len = this.tileMargin + (this.tileSz + this.tileMargin) * this.nodes.length;
+ return len > (this.wideArea ? this.dims[0] : this.dims[1]);
+ },
+ styles(): Record<string,string> {
+ return {
+ position: 'absolute',
+ left: this.pos[0] + 'px',
+ top: this.pos[1] + 'px',
+ width: (this.dims[0] + (this.wideArea || this.hasOverflow ? 0 : -this.scrollBarOffset)) + 'px',
+ height: (this.dims[1] + (!this.wideArea || this.hasOverflow ? 0 : -this.scrollBarOffset)) + 'px',
+ overflowX: this.wideArea ? 'auto' : 'hidden',
+ overflowY: this.wideArea ? 'hidden' : 'auto',
+ // Extra padding for scrollbar inclusion
+ paddingRight: (this.hasOverflow && !this.wideArea ? this.scrollBarOffset : 0) + 'px',
+ paddingBottom: (this.hasOverflow && this.wideArea ? this.scrollBarOffset : 0) + 'px',
+ // For child layout
+ display: 'flex',
+ flexDirection: this.wideArea ? 'row' : 'column',
+ gap: this.tileMargin + 'px',
+ padding: this.tileMargin + 'px',
+ //
+ backgroundColor: '#44403c',
+ boxShadow: this.options.shadowNormal,
+ };
+ },
+ },
+ methods: {
+ onClick(node: LayoutNode){
+ this.$emit('detached-ancestor-clicked', node);
+ },
+ onInnerInfoIconClicked(data: LayoutNode){
+ this.$emit('info-icon-clicked', data);
+ }
+ },
+ components: {
+ TileImg,
+ },
+ emits: ['detached-ancestor-clicked', 'info-icon-clicked'],
+});
+</script>
+
+<template>
+<div :style="styles">
+ <tile-img v-for="node in nodes" :key="node.tolNode.name"
+ :layoutNode="node" :tileSz="tileSz" :options="options"
+ @click="onClick(node)" @info-icon-clicked="onInnerInfoIconClicked"/>
+</div>
+</template>