Skip to content

Commit b366c3d

Browse files
authored
feat: enhance⁠ Tree component capabilities (#33)
* feat: extend component features * chore: update version
1 parent e3bab05 commit b366c3d

File tree

4 files changed

+64
-36
lines changed

4 files changed

+64
-36
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hoppscotch/ui",
3-
"version": "0.2.1",
3+
"version": "0.2.2",
44
"license": "MIT",
55
"description": "Hoppscotch UI",
66
"author": "Hoppscotch ([email protected])",

src/components/smart/Checkbox.vue

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div
3-
class="inline-flex items-center justify-center cursor-pointer group flex-nowrap transition hover:text-secondaryDark"
3+
class="group inline-flex cursor-pointer flex-nowrap items-center justify-center transition hover:text-secondaryDark"
44
role="checkbox"
55
:aria-checked="on"
66
@click="emit('change')"
@@ -15,7 +15,7 @@
1515
/>
1616
<label
1717
:for="checkboxID"
18-
class="pl-0 font-semibold truncate align-middle cursor-pointer"
18+
class="cursor-pointer truncate pl-0 align-middle font-semibold"
1919
>
2020
<slot></slot>
2121
</label>
@@ -36,16 +36,16 @@ let checkboxIDCounter = 564275
3636
<script setup lang="ts">
3737
// Unique ID for checkbox
3838
const checkboxID = `checkbox-${checkboxIDCounter++}`
39-
defineProps({
40-
on: {
41-
type: Boolean,
42-
default: false,
39+
withDefaults(
40+
defineProps<{
41+
on: boolean
42+
name: string
43+
}>(),
44+
{
45+
on: false,
46+
name: "checkbox",
4347
},
44-
name: {
45-
type: String,
46-
default: "checkbox",
47-
},
48-
})
48+
)
4949
5050
const emit = defineEmits<{
5151
(e: "change"): void

src/components/smart/Tree.vue

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
<template>
2-
<div class="flex flex-col flex-1">
2+
<div class="flex flex-1 flex-col">
33
<div
44
v-if="rootNodes.status === 'loaded' && rootNodes.data.length > 0"
55
class="flex flex-col"
66
>
77
<div
88
v-for="rootNode in rootNodes.data"
99
:key="rootNode.id"
10-
class="flex flex-col flex-1"
10+
class="flex flex-1 flex-col"
1111
>
1212
<SmartTreeBranch
1313
:root-nodes-length="rootNodes.data.length"
1414
:node-item="rootNode"
15+
:expand-all="expandAll"
1516
:adapter="adapter as SmartTreeAdapter<T>"
1617
>
1718
<template
@@ -34,14 +35,14 @@
3435
</div>
3536
<div
3637
v-else-if="rootNodes.status === 'loading'"
37-
class="flex flex-col items-center justify-center flex-1 p-4"
38+
class="flex flex-1 flex-col items-center justify-center p-4"
3839
>
3940
<SmartSpinner class="my-4" />
4041
<span class="text-secondaryLight">{{ t?.("state.loading") }}</span>
4142
</div>
4243
<div
4344
v-if="rootNodes.status === 'loaded' && rootNodes.data.length === 0"
44-
class="flex flex-col flex-1"
45+
class="flex flex-1 flex-col"
4546
>
4647
<!-- eslint-disable-next-line vue/no-deprecated-filter -->
4748
<slot name="emptyNode" :node="null as TreeNode<T> | null"></slot>
@@ -63,6 +64,10 @@ const props = defineProps<{
6364
* @template T The type of the data that will be stored in the tree
6465
*/
6566
adapter: SmartTreeAdapter<T>
67+
/**
68+
* open by default
69+
*/
70+
expandAll?: boolean
6671
}>()
6772
6873
/**

src/components/smart/TreeBranch.vue

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
></div>
2121
<div
2222
v-if="childNodes.status === 'loaded' && childNodes.data.length > 0"
23-
class="flex flex-col flex-1 truncate"
23+
class="flex flex-1 flex-col truncate"
2424
:class="{
2525
'bg-divider': highlightNode,
2626
}"
@@ -30,6 +30,7 @@
3030
:key="`${childNode.id}-${childNode.data.type}`"
3131
:node-item="childNode"
3232
:adapter="adapter"
33+
:expand-all="expandAll"
3334
>
3435
<!-- The child slot is given a dynamic name in order to not break Volar -->
3536
<template
@@ -58,43 +59,53 @@
5859

5960
<div
6061
v-if="childNodes.status === 'loading'"
61-
class="flex flex-col items-center justify-center flex-1 p-4"
62+
class="flex flex-1 flex-col items-center justify-center p-4"
6263
>
6364
<SmartSpinner class="my-4" />
6465
<span class="text-secondaryLight">{{ t?.("state.loading") }}</span>
6566
</div>
6667
<div
6768
v-if="childNodes.status === 'loaded' && childNodes.data.length === 0"
68-
class="flex flex-col flex-1"
69+
class="flex flex-1 flex-col"
6970
>
7071
<slot name="emptyNode" :node="nodeItem"></slot>
7172
</div>
7273
</div>
7374
</template>
7475

7576
<script setup lang="ts" generic="T extends any">
76-
import { computed, inject, ref } from "vue"
77+
import { computed, inject, onMounted, ref } from "vue"
7778
import SmartTreeBranch from "./TreeBranch.vue"
7879
import SmartSpinner from "./Spinner.vue"
7980
import { SmartTreeAdapter, TreeNode } from "~/helpers/treeAdapter"
8081
import { HOPP_UI_OPTIONS, HoppUIPluginOptions } from "./../../plugin"
8182
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
8283
83-
const props = defineProps<{
84-
/**
85-
* The node item that will be used to render the tree branch
86-
* @template T The type of the data passed to the tree branch
87-
*/
88-
adapter: SmartTreeAdapter<T>
89-
/**
90-
* The node item that will be used to render the tree branch content
91-
*/
92-
nodeItem: TreeNode<T>
93-
/**
94-
* Total number of rootNode
95-
*/
96-
rootNodesLength?: number
97-
}>()
84+
const props = withDefaults(
85+
defineProps<{
86+
/**
87+
* The node item that will be used to render the tree branch
88+
* @template T The type of the data passed to the tree branch
89+
*/
90+
adapter: SmartTreeAdapter<T>
91+
/**
92+
* The node item that will be used to render the tree branch content
93+
*/
94+
nodeItem: TreeNode<T>
95+
/**
96+
* Total number of rootNode
97+
*/
98+
rootNodesLength?: number
99+
/**
100+
* open by default
101+
*/
102+
expandAll?: boolean
103+
}>(),
104+
{
105+
rootNodesLength: 0,
106+
expandAll: false,
107+
},
108+
)
98109
99110
const CHILD_SLOT_NAME = "default"
100111
@@ -114,15 +125,27 @@ const highlightNode = ref(false)
114125
/**
115126
* Fetch the child nodes from the adapter by passing the node id of the current node
116127
*/
117-
const childNodes = props.adapter.getChildren(props.nodeItem.id, props.nodeItem.data.type)
128+
const childNodes = props.adapter.getChildren(
129+
props.nodeItem.id,
130+
props.nodeItem.data.type,
131+
)
118132
119133
const toggleNodeChildren = () => {
134+
if (props.expandAll) return
120135
if (!childrenRendered.value) childrenRendered.value = true
121136
122137
showChildren.value = !showChildren.value
123138
isNodeOpen.value = !isNodeOpen.value
124139
}
125140
141+
onMounted(() => {
142+
if (props.expandAll) {
143+
childrenRendered.value = true
144+
showChildren.value = true
145+
isNodeOpen.value = true
146+
}
147+
})
148+
126149
const highlightNodeChildren = (id: string | null) => {
127150
if (id) {
128151
highlightNode.value = true

0 commit comments

Comments
 (0)