Skip to content

Instantly share code, notes, and snippets.

@reinerBa
Last active February 23, 2022 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reinerBa/290111271e516b0c63cd5184248d4357 to your computer and use it in GitHub Desktop.
Save reinerBa/290111271e516b0c63cd5184248d4357 to your computer and use it in GitHub Desktop.
bare zero dep vue tree
<script>
/*!
* @License: MIT, (c) Reiner Bamberger
* @Url: https://gist.github.com/reinerBa
*/
import { defineComponent } from 'vue'
const getArraySize =
(value) => Array.isArray(value) ?
1 + [...value.map(getArraySize)].reduce((p, c) => p + c, 0) : 1
// gelber ordner &#x1F4C1;
const comp = defineComponent({
props: ['val', 'nick', 'islast', 'clickFunction'],
data(){return{
hide: false,
isSelected: false
}},
computed:{
isFolder(){
return Array.isArray(this.val)
},
isSelectable(){
return false
},
treeDepth(){
return getArraySize(this.val)
},
hiderHeight () {
return 'height:' + ((this.treeDepth-1)*24+8)+ 'px;'
}
},
methods:{
click(){
if(!!this.clickFunction && typeof this.clickFunction === 'function')
this.clickFunction(this.val, this.isFolder)
}
}
})
export default comp
</script>
<template>
<div v-if="isFolder" class="tree-folder">
<div class="vertical-dash"></div>
<div v-if="!hide" @click="hide = true" class="box-plus folder">&minus;</div>
<div v-else @click="hide = false" class="box-plus folder">+</div>
<span v-if="hide" class="icon">&#x1F5C0;</span>
<span v-else class="icon">&#x1F5C1;</span>
<div class="hider-folder-top"></div>
<div v-if="islast" class="hider-folder" :style="hiderHeight"></div>
<div v-if="hide" class="hider"></div>
<span v-if="isSelectable" @click="isSelected = !isSelected" class="pointer">
<span v-if="isSelected">&#x2611;</span>
<span v-else>&#x2610;</span>
</span>
<span @click="click" class="click">
{{ val.text ? val.text : nick }}
</span>
<template v-if="!hide">
<parent-3
v-for="(v, idx) in val"
:key="v"
:val="v"
:nick="idx"
:islast="idx === val.length - 1"
:clickFunction="clickFunction"
/>
</template>
</div>
<div v-else class="tree-child">
<div class="vertical-dash"></div>
<div v-if="islast" class="hider"></div>
<span @click="click" class="click">
<span class="icon">&#x1F5CB;</span>
<span v-if="isSelectable" @click="isSelected = !isSelected" class="pointer">
<span v-if="isSelected">&#x2611;</span><span v-else>&#x2610;</span>
</span>
{{ val.text ? val.text : val }}
</span>
</div>
</template>
<style scoped>
.vertical-dash{
border-bottom: 1px dotted grey;
position: absolute;
display: inline-flex;
height: 1px;
width: 1.25em;
margin-left: -1.3em;
margin-top: 0.88em;
}
.tree-folder > .vertical-dash{
width: .55em;
}
.hider, .hider-folder, .hider-folder-top{
border-left: 1px solid white;
margin-left: -1px;
height: .5em;
position: absolute;
margin-top: -0.5em;
}
.hider-folder{
margin-left: -30px;
margin-top: -.25em;
}
.hider-folder-top {
margin-top: -1.5em;
}
.tree-folder > .hider {
height: 0.25em;
margin-top: -0.25em;
}
.box-plus, .box-minus{
border: 1px solid black;
display: inline-flex;
line-height: .6em;
width: 0.6em;
height: 0.6em;
font-size: medium;
margin-left: 0.2em;
}
.box-minus{
line-height: .5em;
padding-left: 0.1em;
width: 0.5em;
}
.tree-child::before {
content: "----";
color: transparent;
}
.icon, .pointer, .folder {
font-size: large;
background-color: white;
}
.pointer, .folder{
cursor: pointer;
}
.click{
cursor: default;
}
.tree-folder{
margin-left: 1.75em;
border-left: 1px dotted grey;
}
.folder{
margin-left: -35px;
margin-right: 11px;
background-color: white;
}
.tree-child {
display: block;
}
</style>
@reinerBa
Copy link
Author

reinerBa commented Feb 22, 2022

Just a tree like a folder-file tree with only span, div and utf8 characters. Totaly css-framework agnostic 😊

Example with almost random numbers:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment