Skip to content

Commit

Permalink
feat: enhance⁠ Tree component capabilities (#33)
Browse files Browse the repository at this point in the history
* feat: extend component features

* chore: update version
  • Loading branch information
anwarulislam authored Oct 22, 2024
1 parent e3bab05 commit b366c3d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hoppscotch/ui",
"version": "0.2.1",
"version": "0.2.2",
"license": "MIT",
"description": "Hoppscotch UI",
"author": "Hoppscotch ([email protected])",
Expand Down
22 changes: 11 additions & 11 deletions src/components/smart/Checkbox.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
class="inline-flex items-center justify-center cursor-pointer group flex-nowrap transition hover:text-secondaryDark"
class="group inline-flex cursor-pointer flex-nowrap items-center justify-center transition hover:text-secondaryDark"
role="checkbox"
:aria-checked="on"
@click="emit('change')"
Expand All @@ -15,7 +15,7 @@
/>
<label
:for="checkboxID"
class="pl-0 font-semibold truncate align-middle cursor-pointer"
class="cursor-pointer truncate pl-0 align-middle font-semibold"
>
<slot></slot>
</label>
Expand All @@ -36,16 +36,16 @@ let checkboxIDCounter = 564275
<script setup lang="ts">
// Unique ID for checkbox
const checkboxID = `checkbox-${checkboxIDCounter++}`
defineProps({
on: {
type: Boolean,
default: false,
withDefaults(
defineProps<{
on: boolean
name: string
}>(),
{
on: false,
name: "checkbox",
},
name: {
type: String,
default: "checkbox",
},
})
)
const emit = defineEmits<{
(e: "change"): void
Expand Down
13 changes: 9 additions & 4 deletions src/components/smart/Tree.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<template>
<div class="flex flex-col flex-1">
<div class="flex flex-1 flex-col">
<div
v-if="rootNodes.status === 'loaded' && rootNodes.data.length > 0"
class="flex flex-col"
>
<div
v-for="rootNode in rootNodes.data"
:key="rootNode.id"
class="flex flex-col flex-1"
class="flex flex-1 flex-col"
>
<SmartTreeBranch
:root-nodes-length="rootNodes.data.length"
:node-item="rootNode"
:expand-all="expandAll"
:adapter="adapter as SmartTreeAdapter<T>"
>
<template
Expand All @@ -34,14 +35,14 @@
</div>
<div
v-else-if="rootNodes.status === 'loading'"
class="flex flex-col items-center justify-center flex-1 p-4"
class="flex flex-1 flex-col items-center justify-center p-4"
>
<SmartSpinner class="my-4" />
<span class="text-secondaryLight">{{ t?.("state.loading") }}</span>
</div>
<div
v-if="rootNodes.status === 'loaded' && rootNodes.data.length === 0"
class="flex flex-col flex-1"
class="flex flex-1 flex-col"
>
<!-- eslint-disable-next-line vue/no-deprecated-filter -->
<slot name="emptyNode" :node="null as TreeNode<T> | null"></slot>
Expand All @@ -63,6 +64,10 @@ const props = defineProps<{
* @template T The type of the data that will be stored in the tree
*/
adapter: SmartTreeAdapter<T>
/**
* open by default
*/
expandAll?: boolean
}>()
/**
Expand Down
63 changes: 43 additions & 20 deletions src/components/smart/TreeBranch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
></div>
<div
v-if="childNodes.status === 'loaded' && childNodes.data.length > 0"
class="flex flex-col flex-1 truncate"
class="flex flex-1 flex-col truncate"
:class="{
'bg-divider': highlightNode,
}"
Expand All @@ -30,6 +30,7 @@
:key="`${childNode.id}-${childNode.data.type}`"
:node-item="childNode"
:adapter="adapter"
:expand-all="expandAll"
>
<!-- The child slot is given a dynamic name in order to not break Volar -->
<template
Expand Down Expand Up @@ -58,43 +59,53 @@

<div
v-if="childNodes.status === 'loading'"
class="flex flex-col items-center justify-center flex-1 p-4"
class="flex flex-1 flex-col items-center justify-center p-4"
>
<SmartSpinner class="my-4" />
<span class="text-secondaryLight">{{ t?.("state.loading") }}</span>
</div>
<div
v-if="childNodes.status === 'loaded' && childNodes.data.length === 0"
class="flex flex-col flex-1"
class="flex flex-1 flex-col"
>
<slot name="emptyNode" :node="nodeItem"></slot>
</div>
</div>
</template>

<script setup lang="ts" generic="T extends any">
import { computed, inject, ref } from "vue"
import { computed, inject, onMounted, ref } from "vue"
import SmartTreeBranch from "./TreeBranch.vue"
import SmartSpinner from "./Spinner.vue"
import { SmartTreeAdapter, TreeNode } from "~/helpers/treeAdapter"
import { HOPP_UI_OPTIONS, HoppUIPluginOptions } from "./../../plugin"
const { t } = inject<HoppUIPluginOptions>(HOPP_UI_OPTIONS) ?? {}
const props = defineProps<{
/**
* The node item that will be used to render the tree branch
* @template T The type of the data passed to the tree branch
*/
adapter: SmartTreeAdapter<T>
/**
* The node item that will be used to render the tree branch content
*/
nodeItem: TreeNode<T>
/**
* Total number of rootNode
*/
rootNodesLength?: number
}>()
const props = withDefaults(
defineProps<{
/**
* The node item that will be used to render the tree branch
* @template T The type of the data passed to the tree branch
*/
adapter: SmartTreeAdapter<T>
/**
* The node item that will be used to render the tree branch content
*/
nodeItem: TreeNode<T>
/**
* Total number of rootNode
*/
rootNodesLength?: number
/**
* open by default
*/
expandAll?: boolean
}>(),
{
rootNodesLength: 0,
expandAll: false,
},
)
const CHILD_SLOT_NAME = "default"
Expand All @@ -114,15 +125,27 @@ const highlightNode = ref(false)
/**
* Fetch the child nodes from the adapter by passing the node id of the current node
*/
const childNodes = props.adapter.getChildren(props.nodeItem.id, props.nodeItem.data.type)
const childNodes = props.adapter.getChildren(
props.nodeItem.id,
props.nodeItem.data.type,
)
const toggleNodeChildren = () => {
if (props.expandAll) return
if (!childrenRendered.value) childrenRendered.value = true
showChildren.value = !showChildren.value
isNodeOpen.value = !isNodeOpen.value
}
onMounted(() => {
if (props.expandAll) {
childrenRendered.value = true
showChildren.value = true
isNodeOpen.value = true
}
})
const highlightNodeChildren = (id: string | null) => {
if (id) {
highlightNode.value = true
Expand Down

0 comments on commit b366c3d

Please sign in to comment.