feat: add new shared component tree view (prototype)
This commit is contained in:
parent
c8072d10ed
commit
4cd0fdc085
1 changed files with 98 additions and 0 deletions
98
src/components/shared/TreeView.vue
Normal file
98
src/components/shared/TreeView.vue
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Icon } from '@iconify/vue';
|
||||||
|
type Node = {
|
||||||
|
[key: string]: any;
|
||||||
|
selected?: boolean;
|
||||||
|
children?: Node[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
level?: number;
|
||||||
|
keyTitle?: string;
|
||||||
|
keySubtitle?: string;
|
||||||
|
decoration?: {
|
||||||
|
level?: number;
|
||||||
|
bg?: string;
|
||||||
|
fg?: string;
|
||||||
|
icon?: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const currentStyle = props.decoration?.find((v) => {
|
||||||
|
return v.level === (props.level || 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodes = defineModel<Node[]>('nodes', { required: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="tree-container">
|
||||||
|
<div v-for="node in nodes" class="tree-item">
|
||||||
|
<slot
|
||||||
|
v-if="$slots['item']"
|
||||||
|
name="item"
|
||||||
|
:data="{ node, onclick: () => (node.selected = !node.selected) }"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<label class="row items-center">
|
||||||
|
<input
|
||||||
|
class="item__checkbox"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="node.selected"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
v-if="currentStyle?.icon"
|
||||||
|
:icon="currentStyle.icon"
|
||||||
|
class="item__icon"
|
||||||
|
/>
|
||||||
|
<div class="column">
|
||||||
|
<span class="item__title">
|
||||||
|
{{ node[keyTitle || 'title'] || 'No Title' }}
|
||||||
|
</span>
|
||||||
|
<span class="item__subtitle">
|
||||||
|
{{ node[keySubtitle || 'subtitle'] || 'No Subtitle' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
<div class="q-pl-xl">
|
||||||
|
<TreeView
|
||||||
|
v-if="node.children"
|
||||||
|
v-model:nodes="node.children"
|
||||||
|
:level="(level || 0) + 1"
|
||||||
|
:decoration
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css">
|
||||||
|
.tree-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
|
||||||
|
& .tree-item {
|
||||||
|
& .item__checkbox {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .item__icon {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .item__title {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
& .item__subtitle {
|
||||||
|
font-size: 80%;
|
||||||
|
color: hsla(var(--text-mute-2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue