Skip to content

any-design/file-tree

Repository files navigation

@any-design/file-tree

@any-design/file-tree is a custom fork of markhu-file-tree

This package is a customizable draggable file tree component for Vue 3 that draws inspiration from the VSCode resource explorer.

Feature

  • All nodes in the tree have a type of either 'folder' or 'file'.
  • Folders can be expanded regardless of whether they are empty or not.
  • Items can be dragged and dropped into folders, but not into files.
  • 'Folder' or 'file' names can be renamed to new names.
  • Multiple files can be selected using the Ctrl/Shift keys.
  • The selected item can be navigated using the up and down arrow keys.

Install

npm i @any-design/file-tree

Quick start

<script setup>
import { ref } from 'vue';
import '@any-design/file-tree/dist/style.css';

const treeData = ref([
  {
    title: 'Documents',
    path: '/users/Jim/Documents',
    type: 'folder',
    children: [
      {
        title: 'File1.txt',
        path: '/users/Jim/Documents/File1.txt',
        type: 'file',
      },
      {
        title: 'File2.txt',
        path: '/users/Jim/Documents/File2.txt',
        type: 'file',
      },
    ],
  },
  {
    title: 'Pictures',
    path: '/users/Jim/Pictures',
    type: 'folder',
    children: [
      {
        title: 'Image1.jpg',
        path: '/users/Jim/Pictures/Image1.jpg',
        type: 'file',
      },
      {
        title: 'Image2.jpg',
        path: '/users/Jim/Pictures/Image2.jpg',
        type: 'file',
      },
    ],
  },
]);
</script>

<template>
  <file-tree v-model="treeData"></file-tree>
</template>

The modelValue property is an object of TreeNode nodes:

export interface TreeNode {
  title: string;
  path: string;
  type: string;
  expanded?: boolean;
  selected?: boolean;
  focused?: boolean;
  children?: TreeNode[];
  addingFile?: boolean;
  addingFolder?: boolean;
  editing?: boolean;
}

Props

prop type default description
modelValue TreeNode A tree to show. The root node will not show in ui

Events

Event Name Callback Parameters Purpose
@nodeSelect items: TreeNode[] Triggered when nodes are selected.
@nodeCreate node: TreeNode, title: string Triggered when a new node is created.
@nodeRename node: TreeNode, newTitle: string, oldTitle: string Triggered when a node is renamed.
@nodeExpand node: TreeNode Triggered when a node is expanded.
@nodeCollapse node: TreeNode Triggered when a node is collapsed.
@nodeDrop newPath: string, oldPath: string Triggered when a node is dragged and dropped to a new location.
@nodeMove newPath: string, oldPath: string Triggered when a node is moved to a new location.
@nodeContextmenu e: MouseEvent, d: TreeNode Triggered when a node's context menu is opened.
@update:modelValue node: TreeNode Tree data has been updated

Methods

method description

Slots

Slot Name Parameters Purpose
title {nodeData} Used to customize the title content of a node.
toggler {nodeData} Used to customize the expand/collapse icon of a node.
icon {nodeData} Used to customize the icon of a node.

Examples

Customize title, toggle icon and file icon with slots.

Note: In this example, we use Font Awesome as icon lib.

<file-tree
  :v-model="treeData"
  @nodeSelect="onNodeSelect"
  @fileCreate="onFileCreate"
  @folderCreate="onFolderCreate"
  @nodeRename="onNodeRename"
  @nodeExpand="onNodeExpand"
  @nodeCollapse="onNodeCollapse"
  @nodeDrop="onNodeDrop"
  @nodeMove="onNodeMove"
  @nodeContextmenu="onNodeContextmenu"
>
  <template v-slot:title="{nodeData}">{{ nodeData.title }}</template>
  <template v-slot:toggler="{nodeData}">
    <span style="margin-right: 5px">
      <i class="fa-solid fa-chevron-down" v-if="nodeData.expanded"></i>
      <i class="fa-solid fa-chevron-right" v-else></i>
    </span>
  </template>
  <template v-slot:icon="{nodeData}">
    <span style="margin-right: 5px">
      <i class="fa-regular fa-folder" v-if="nodeData.type==='folder'"></i>
      <i class="fa-regular fa-file-audio" v-else-if="nodeData.title.endsWith('.mp3')"></i>
      <i class="fa-regular fa-file-image" v-else-if="nodeData.title.endsWith('.jpg')"></i>
      <i class="fa-solid fa-file-word" v-else-if="nodeData.title.endsWith('.doc')"></i>
      <i class="fa-solid fa-file-pdf" v-else-if="nodeData.title.endsWith('.pdf')"></i>
      <i class="fa-solid fa-file-csv" v-else-if="nodeData.title.endsWith('.csv')"></i>
      <i class="fa-regular fa-file-lines" v-else-if="nodeData.title.endsWith('.txt')"></i>
      <i class="fa-regular fa-file" v-else></i>
    </span>
  </template>
</file-tree>