diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/ParentBar.vue | 18 | ||||
| -rw-r--r-- | src/components/ParentBarTile.vue | 40 | ||||
| -rw-r--r-- | src/components/Tile.vue | 92 | ||||
| -rw-r--r-- | src/components/TileImg.vue | 71 | ||||
| -rw-r--r-- | src/components/TileTree.vue | 4 |
5 files changed, 112 insertions, 113 deletions
diff --git a/src/components/ParentBar.vue b/src/components/ParentBar.vue index 242f715..8cd1f3b 100644 --- a/src/components/ParentBar.vue +++ b/src/components/ParentBar.vue @@ -1,8 +1,17 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import {LayoutNode} from '../lib'; -import ParentBarTile from './ParentBarTile.vue' +import TileImg from './TileImg.vue' +const defaultTileImgOptions = { + borderRadius: 5, + shadowNormal: '0 0 2px black', + shadowHighlight: '0 0 1px 2px greenyellow', + imgTilePadding: 4, + imgTileFontSz: 15, + imgTileColor: '#fafaf9', + expandableImgTileColor: 'greenyellow', +} export default defineComponent({ props: { pos: {type: Array as unknown as PropType<[number,number]>, required: true}, @@ -13,6 +22,7 @@ export default defineComponent({ return { tileMargin: 5, //px (gap between separated-parent tiles) scrollBarOffset: 10, //px (gap for scrollbar, used to prevent overlap with tiles) + tileImgOptions: {...defaultTileImgOptions}, }; }, computed: { @@ -46,14 +56,14 @@ export default defineComponent({ }, }, components: { - ParentBarTile, + TileImg, }, }); </script> <template> <div :style="styles"> - <parent-bar-tile v-for="node in nodes" :key="node.tolNode.name" - :layoutNode="node" :tileSz="tileSz"/> + <tile-img v-for="node in nodes" :key="node.tolNode.name" + :layoutNode="node" :tileSz="tileSz" :options="tileImgOptions"/> </div> </template> diff --git a/src/components/ParentBarTile.vue b/src/components/ParentBarTile.vue deleted file mode 100644 index 7e17ba6..0000000 --- a/src/components/ParentBarTile.vue +++ /dev/null @@ -1,40 +0,0 @@ -<script lang="ts"> -import {defineComponent, PropType} from 'vue'; -import {LayoutNode} from '../lib'; - -export default defineComponent({ - props: { - layoutNode: {type: Object as PropType<LayoutNode>, required: true}, - tileSz: {type: Number, required: true}, //px (length of tile edge) - }, - computed: { - styles(): Record<string,string> { - return { - border: '1px black solid', - width: this.tileSz + 'px', - height: this.tileSz + 'px', - minWidth: this.tileSz + 'px', - minHeight: this.tileSz + 'px', - backgroundImage: 'url(\'/img/' + this.layoutNode.tolNode.name.replaceAll('\'', '\\\'') + '.png\')', - backgroundSize: 'cover', - borderRadius: '5px', - }; - }, - headerStyles(): Record<string,string> { - return { - color: 'greenyellow', - // For ellipsis - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - }; - }, - }, -}); -</script> - -<template> - <div :style="styles"> - <div :style="headerStyles">{{layoutNode.tolNode.name}}</div> - </div> -</template> diff --git a/src/components/Tile.vue b/src/components/Tile.vue index 2a94606..09f3817 100644 --- a/src/components/Tile.vue +++ b/src/components/Tile.vue @@ -1,19 +1,19 @@ <script lang="ts"> import {defineComponent, PropType} from 'vue'; import {LayoutNode} from '../lib'; +import TileImg from './TileImg.vue'; // Configurable settings const defaultOptions = { borderRadius: 5, //px shadowNormal: '0 0 2px black', - shadowWithHover: '0 0 1px 2px greenyellow', + shadowHighlight: '0 0 1px 2px greenyellow', dblClickWait: 200, //ms // For leaf tiles - leafHeaderX: 4, //px - leafHeaderY: 4, //px - leafHeaderFontSz: 15, //px - leafHeaderColor: '#fafaf9', - expandableLeafHeaderColor: 'greenyellow', //yellow, greenyellow, turquoise, + imgTilePadding: 4, //px + imgTileFontSz: 15, //px + imgTileColor: '#fafaf9', + expandableImgTileColor: 'greenyellow', //yellow, greenyellow, turquoise, // For non-leaf tile-groups nonLeafBgColors: ['#44403c', '#57534e'], //tiles at depth N use the Nth color, repeating from the start as needed nonLeafHeaderFontSz: 15, //px @@ -73,32 +73,7 @@ export default defineComponent({ '--nonLeafBgColor': this.nonLeafBgColor, '--tileSpacing': this.tileSpacing + 'px', '--shadowNormal': this.options.shadowNormal, - '--shadowWithHover': this.options.shadowWithHover, - }; - }, - leafStyles(): Record<string,string> { - return { - width: '100%', - height: '100%', - backgroundImage: 'url(\'/img/' + this.layoutNode.tolNode.name.replaceAll('\'', '\\\'') + '.png\')', - backgroundSize: 'cover', - borderRadius: this.options.borderRadius + 'px', - }; - }, - leafHeaderStyles(): Record<string,string> { - return { - position: 'absolute', - left: this.options.leafHeaderX + 'px', - top: this.options.leafHeaderY + 'px', - maxWidth: (this.layoutNode.hidden ? 0 : this.layoutNode.dims[0] - this.options.leafHeaderX * 2) + 'px', - height: this.options.leafHeaderFontSz + 'px', - lineHeight: this.options.leafHeaderFontSz + 'px', - fontSize: this.options.leafHeaderFontSz + 'px', - color: this.isExpandable ? this.options.expandableLeafHeaderColor : this.options.leafHeaderColor, - // For ellipsis - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', + '--shadowHighlight': this.options.shadowHighlight, }; }, nonLeafStyles(): Record<string,string> { @@ -171,7 +146,6 @@ export default defineComponent({ return; } let prepForTransition = () => { - (this.$refs.leaf as Element).classList.replace('shadow-highlight', 'shadow-normal'); // Temporary changes to prevent content overlap and overflow this.zIdx = 1; this.overflow = 'hidden'; @@ -220,52 +194,43 @@ export default defineComponent({ this.$emit('header-dbl-clicked', data); }, // For coloured-outlines on hovered-over leaf-tiles or non-leaf-headers - onMouseEnter(evt: Event){ - if (!this.isLeaf){ - (this.$refs.nonLeaf as Element).classList.replace('shadow-normal', 'shadow-highlight'); - let sepSweptArea = (this.$refs.sepSweptArea as Element | null); - if (sepSweptArea != null){ - sepSweptArea.classList.replace('shadow-normal', 'shadow-highlight'); - } - } else if (this.isExpandable){ - (evt.target as Element).classList.replace('shadow-normal', 'shadow-highlight'); + onNonLeafMouseEnter(evt: Event){ + (this.$refs.nonLeaf as Element).classList.replace('shadow-normal', 'shadow-highlight'); + let sepSweptArea = (this.$refs.sepSweptArea as Element | null); + if (sepSweptArea != null){ + sepSweptArea.classList.replace('shadow-normal', 'shadow-highlight'); } }, - onMouseLeave(evt: Event){ - if (!this.isLeaf){ - (this.$refs.nonLeaf as Element).classList.replace('shadow-highlight', 'shadow-normal'); - let sepSweptArea = this.$refs.sepSweptArea as Element | null; - if (sepSweptArea != null){ - sepSweptArea.classList.replace('shadow-highlight', 'shadow-normal'); - } - } else if (this.isExpandable){ - (evt.target as Element).classList.replace('shadow-highlight', 'shadow-normal'); + onNonLeafMouseLeave(evt: Event){ + (this.$refs.nonLeaf as Element).classList.replace('shadow-highlight', 'shadow-normal'); + let sepSweptArea = this.$refs.sepSweptArea as Element | null; + if (sepSweptArea != null){ + sepSweptArea.classList.replace('shadow-highlight', 'shadow-normal'); } }, }, name: 'tile', // Need this to use self in template + components: { + TileImg, + }, emits: ['leaf-clicked', 'header-clicked', 'leaf-dbl-clicked', 'header-dbl-clicked'], }); </script> <template> <div :style="tileStyles"> - <div v-if="isLeaf" :style="leafStyles" ref="leaf" - :class="['shadow-normal'].concat(isExpandable ? ['hover:cursor-pointer'] : [])" - @click="onLeafClick($event)" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"> - <div :style="{borderRadius: options.borderRadius + 'px'}" class="scrim-upper-half"/> - <div :style="leafHeaderStyles">{{layoutNode.tolNode.name}}</div> - </div> + <tile-img v-if="isLeaf" :layoutNode="layoutNode" :tileSz="layoutNode.dims[0]" :options="options" + @click="onLeafClick"/> <div v-else :style="nonLeafStyles" class="shadow-normal" ref="nonLeaf"> <h1 v-if="showHeader" :style="nonLeafHeaderStyles" class="hover:cursor-pointer" - @click="onHeaderClick($event)" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"> + @click="onHeaderClick($event)" @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave"> {{layoutNode.tolNode.name}} </h1> <div :style="sepSweptAreaStyles" ref="sepSweptArea" :class="[layoutNode?.sepSweptArea?.sweptLeft ? 'hide-right-edge' : 'hide-top-edge', 'shadow-normal']"> <h1 v-if="layoutNode?.sepSweptArea?.sweptLeft === false" :style="nonLeafHeaderStyles" class="hover:cursor-pointer" - @click="onHeaderClick($event)" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"> + @click="onHeaderClick($event)" @mouseenter="onNonLeafMouseEnter" @mouseleave="onNonLeafMouseLeave"> {{layoutNode.tolNode.name}} </h1> </div> @@ -296,15 +261,8 @@ export default defineComponent({ width: calc(100% + var(--tileSpacing)); height: var(--tileSpacing); } -.scrim-upper-half { - position: absolute; - top: 0; - height: 50%; - width: 100%; - background-image: linear-gradient(to top, rgba(0,0,0,0), rgba(0,0,0,0.4)); -} .shadow-highlight { - box-shadow: var(--shadowWithHover); + box-shadow: var(--shadowHighlight); } .shadow-normal { box-shadow: var(--shadowNormal); diff --git a/src/components/TileImg.vue b/src/components/TileImg.vue new file mode 100644 index 0000000..c03ba84 --- /dev/null +++ b/src/components/TileImg.vue @@ -0,0 +1,71 @@ +<script lang="ts"> +import {defineComponent, PropType} from 'vue'; +import {LayoutNode} from '../lib'; + +export default defineComponent({ + props: { + layoutNode: {type: Object as PropType<LayoutNode>, required: true}, + tileSz: {type: Number, required: true}, //px (edge length) + options: {type: Object, required: true}, + }, + data(){ + return { + highlight: false, + }; + }, + computed: { + isExpandable(){ + return this.layoutNode.tolNode.children.length > 0; + }, + styles(): Record<string,string> { + return { + border: '1px black solid', + width: this.tileSz + 'px', + height: this.tileSz + 'px', + backgroundImage: + 'linear-gradient(to bottom, rgba(0,0,0,0.4), rgba(0,0,0,0) 40%),' + + 'url(\'/img/' + this.layoutNode.tolNode.name.replaceAll('\'', '\\\'') + '.png\')', + backgroundSize: 'cover', + borderRadius: this.options.borderRadius + 'px', + boxShadow: (this.highlight ? this.options.shadowHighlight : this.options.shadowNormal), + }; + }, + headerStyles(): Record<string,string> { + return { + height: (this.options.imgTileFontSz + this.options.imgTilePadding * 2) + 'px', + lineHeight: this.options.imgTileFontSz + 'px', + fontSize: this.options.imgTileFontSz + 'px', + padding: this.options.imgTilePadding + 'px', + color: this.isExpandable ? this.options.expandableImgTileColor : this.options.imgTileColor, + // For ellipsis + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }; + }, + }, + methods: { + onMouseEnter(evt: Event){ + if (this.isExpandable){ + this.highlight = true; + } + }, + onMouseLeave(evt: Event){ + if (this.isExpandable){ + this.highlight = false; } + }, + onClick(evt: Event){ + if (this.isExpandable){ + this.highlight = false; + } + }, + }, +}); +</script> + +<template> +<div :style="styles" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @click="onClick" + :class="isExpandable ? ['hover:cursor-pointer'] : []"> + <div :style="headerStyles">{{layoutNode.tolNode.name}}</div> +</div> +</template> diff --git a/src/components/TileTree.vue b/src/components/TileTree.vue index 3ea21b4..d36949e 100644 --- a/src/components/TileTree.vue +++ b/src/components/TileTree.vue @@ -96,9 +96,9 @@ export default defineComponent({ }, parentBarDims(){ if (this.wideArea){ - return [this.parentBarSz, this.dims[1]] + return [this.parentBarSz, this.dims[1]] as [number, number]; } else { - return [this.dims[0], this.parentBarSz]; + return [this.dims[0], this.parentBarSz] as [number, number]; } }, styles(): Record<string,string> { |
