{"id":22373803,"url":"https://github.com/shunjizhan/react-folder-tree","last_synced_at":"2025-04-05T10:10:06.608Z","repository":{"id":37683994,"uuid":"141231340","full_name":"shunjizhan/react-folder-tree","owner":"shunjizhan","description":"A versatile react treeview library that supports custom icons and event handlers","archived":false,"fork":false,"pushed_at":"2024-06-18T00:50:37.000Z","size":18733,"stargazers_count":126,"open_issues_count":56,"forks_count":47,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T09:09:28.446Z","etag":null,"topics":["folder","folder-picker","folder-structure","folder-tooling","folder-tree","folder-viewer","folders","npm","npm-module","npm-package","react","reactjs","recursion","recursion-problem","recursion-tree","recursion-tree-visualiser","recursion-tree-visualizer","recursions","tree-structure","treeview"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/react-folder-tree","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shunjizhan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-17T04:30:52.000Z","updated_at":"2025-03-02T02:19:08.000Z","dependencies_parsed_at":"2024-06-18T16:59:57.571Z","dependency_job_id":"4629588a-1e2d-4da7-9976-cdea3f586b9e","html_url":"https://github.com/shunjizhan/react-folder-tree","commit_stats":{"total_commits":199,"total_committers":5,"mean_commits":39.8,"dds":0.5477386934673367,"last_synced_commit":"a70a8dd1c62618d9e67749a22bf6b567d4dbc3e1"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunjizhan%2Freact-folder-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunjizhan%2Freact-folder-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunjizhan%2Freact-folder-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunjizhan%2Freact-folder-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shunjizhan","download_url":"https://codeload.github.com/shunjizhan/react-folder-tree/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247318745,"owners_count":20919484,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["folder","folder-picker","folder-structure","folder-tooling","folder-tree","folder-viewer","folders","npm","npm-module","npm-package","react","reactjs","recursion","recursion-problem","recursion-tree","recursion-tree-visualiser","recursion-tree-visualizer","recursions","tree-structure","treeview"],"created_at":"2024-12-04T21:14:22.946Z","updated_at":"2025-04-05T10:10:06.576Z","avatar_url":"https://github.com/shunjizhan.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Folder Tree\n[![travis build](https://img.shields.io/travis/com/shunjizhan/react-folder-tree?logo=travis)](https://travis-ci.com/shunjizhan/react-folder-tree) [![codecov](https://codecov.io/gh/shunjizhan/react-folder-tree/branch/master/graph/badge.svg?token=26EEM3JIUY)](https://codecov.io/gh/shunjizhan/react-folder-tree) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-folder-tree?color=light%20green\u0026label=zipped%20only\u0026logo=webpack)  \n[![npm](https://img.shields.io/npm/v/react-folder-tree?logo=npm)](https://www.npmjs.com/package/react-folder-tree) [![npm](https://img.shields.io/npm/dm/react-folder-tree?logo=DocuSign\u0026color=blue)](https://www.npmjs.com/package/react-folder-tree) ![GitHub top language](https://img.shields.io/github/languages/top/shunjizhan/react-folder-tree?logo=react)\n\nA versatile and customizable react treeview library. Features:  \n✅ custom icons  \n✅ custom event handlers  \n✅ inline add, modify, and delete tree nodes  \n✅ checkbox with half check (indeterminate check)  \n✅ read-only mode\n\nIt uses [use-tree-state](https://www.npmjs.com/package/use-tree-state) hook internally for convenient state management.\n### Quick Preview\n![folder-tree-demo](/assets/folder-tree-demo.gif)\n\n### Live Demos\nlive demos and code examples can be found [here](https://shunjizhan.github.io/react-folder-tree-demos/)\n\n---\n## Basic Usage\n### 🌀 install\n```bash\n$ yarn add react-folder-tree\n$ npm install react-folder-tree --save\n```\n### 🌀 basic tree\n```tsx\nimport FolderTree, { testData } from 'react-folder-tree';\nimport 'react-folder-tree/dist/style.css';\n\nconst BasicTree = () =\u003e {\n  const onTreeStateChange = (state, event) =\u003e console.log(state, event);\n\n  return (\n    \u003cFolderTree\n      data={ testData }\n      onChange={ onTreeStateChange }\n    /\u003e\n  );\n};\n```\n\n### 🌀 custom initial state\nInitial tree state is an object that describes a nested tree node structure, which looks like:\n```jsx\n{\n  // reserved keys, can customize initial value\n  name: 'root node',  \n  checked (optional): 0 (unchecked, default) | 0.5 (half checked) | 1(checked),\n  isOpen (optional): true (default) | false,\n  children (optional): [array of treenode],\n\n  // internal keys (auto generated), plz don't include them in the initial data\n  path: [],    // path is an array of indexes to this node from root node\n  _id: 0,\n\n  // not reserved, can carry any extra info about this node\n  nickname (optional): 'pikachu',\n  url (optional): 'url of this node',\n}\n```\n`checked` and `isOpen` status could be auto initialized by props `initCheckedStatus` and `initOpenStatus`. We can also provide data with custom `checked` and `isOpen` status, and set `initCheckedStatus` and `initOpenStatus` to `'custom'`.\n\nThis example shows how to render a tree with custom initial state\n```tsx\nconst treeState = {\n  name: 'root [half checked and opened]',\n  checked: 0.5,   // half check: some children are checked\n  isOpen: true,   // this folder is opened, we can see it's children\n  children: [\n    { name: 'children 1 [not checked]', checked: 0 },\n    {\n      name: 'children 2 [half checked and not opened]',\n      checked: 0.5,\n      isOpen: false,\n      children: [\n        { name: 'children 2-1 [not checked]', checked: 0 },\n        { name: 'children 2-2 [checked]', checked: 1 },\n      ],\n    },\n  ],\n};\n\nconst CustomInitState = () =\u003e (\n  \u003cFolderTree\n    data={ treeState }\n    initCheckedStatus='custom'  // default: 0 [unchecked]\n    initOpenStatus='custom'     // default: 'open'\n  /\u003e\n);\n```\n\n### 🌀 hate checkbox?\n```jsx\n\u003cFolderTree\n  data={ treeState }\n  showCheckbox={ false }    // default: true\n/\u003e\n```\n\n### 🌀 love indentation?\n```jsx\n\u003cFolderTree\n  data={ treeState }\n  indentPixels={ 99999 }    // default: 30\n/\u003e\n```\n\n### 🌀 read only?\nwe can use it as a classical view-only tree\n```jsx\n\u003cFolderTree\n  data={ treeState }\n  showCheckbox={ false }    // hiding checkbox is not required but recommended for better UX\n  readOnly                  // \u003c== here!!\n/\u003e\n```\n---\n## Advanced Usage\n### 🔥 sync tree state\nIn order to perform more complex operations, we can sync and keep track of the current tree state outside.\n\nThis example shows how to download all selected files.\n```jsx\nconst SuperApp = () =\u003e {\n  const [treeState, setTreeState] = useState(initState);\n  const onTreeStateChange = (state, event) =\u003e setTreeState(state);\n\n  const onDownload = () =\u003e downloadAllSelected(treeState);\n\n  return (\n    \u003c\u003e\n      \u003cFolderTree\n        data={ initState }\n        onChange={ onTreeStateChange }\n      /\u003e\n      \u003cDownloadButton onClick={ onDownload } /\u003e\n    \u003c/\u003e\n  );\n};\n```\n\n### 🔥 custom icons \nThere are 9 icons and all of them are customizable.\n- FileIcon\n- FolderIcon\n- FolderOpenIcon\n- EditIcon\n- DeleteIcon\n- CancelIcon\n- CaretRightIcon\n- CaretDownIcon\n- OKIcon\n\nThis example shows how to customize the FileIcon (same interface for all other icons).\n```jsx\nimport { FaBitcoin } from 'react-icons/fa';\n\nconst BitcoinApp = () =\u003e {\n  const FileIcon = ({ onClick: defaultOnClick, nodeData }) =\u003e {\n    const {\n      path,\n      name,\n      checked,\n      isOpen,\n      ...restData\n    } = nodeData;\n\n    // custom event handler\n    const handleClick = () =\u003e {   \n      doSthBad({ path, name, checked, isOpen, ...restData });\n\n      defaultOnClick();\n    };\n\n    // custom Style\n    return \u003cFaBitcoin onClick={ handleClick } /\u003e;\n  };\n\n  return (\n    \u003cFolderTree\n      data={ initState }\n      iconComponents={{\n        FileIcon,\n        /* other custom icons ... */\n      }}\n    /\u003e\n  );\n};\n```\n\n### 🔥 hide icons / disable interaction\nThis usage is a subset of custom icons.\n\nFor example, if we want to disable editing, we can hide `EditIcon` by passing in a dummy custom icon, so nothing will be rendered.\n```tsx\nconst EditIcon = (...args) =\u003e null;\n```\n\nA little more complex but more flexible way is to have extra node data, say `editable`, then build a custom icon that utilize this data\n```ts\nconst EditIcon = ({ onClick: defaultOnClick, nodeData }) =\u003e {\n  const { editable } = nodeData;\n\n  // if this node is editable, render an EditIcon, otherwise render air\n  return editable ? (\u003cFaEdit onClick={ defaultOnClick } /\u003e) : null;\n\n  // or render a 'not editable' icon\n  return editable ? (\u003cFaEdit onClick={ defaultOnClick } /\u003e) : (\u003cDontEdit /\u003e));\n};\n```\n\n### 🔥 custom `onClick` for node names\nThis example shows how to download the file when click on the node name.\n```tsx\nconst dataWithUrl = {\n  name: 'secret crypto file',\n  url: 'polkadot.network',      // wew can provide any custom data to the FolderTree!\n  // ...\n};\n\nconst onNameClick = ({ defaultOnClick, nodeData }) =\u003e {\n  defaultOnClick();\n\n  const {\n    // internal data\n    path, name, checked, isOpen, \n    // custom data\n    url, ...whateverRest\n  } = nodeData;\n\n  download(url);\n};\n\nconst Downloader = () =\u003e (\n  \u003cFolderTree\n    data={ dataWithUrl }\n    onNameClick={ onNameClick }\n  /\u003e\n);\n```\n\n---\n## APIs Summary\n\n| prop              | description                             | type     | options                                        |\n|-------------------|-----------------------------------------|----------|------------------------------------------------|\n| data              | initial tree state data (required)      | object   | N/A                                            |\n| initCheckedStatus | initial check status of all nodes       | string   | 'unchecked' (default) \\| 'checked' \\| 'custom' |\n| initOpenStatus    | initial open status of all treenodes    | string   | 'open' (default) \\| 'closed' \\| 'custom'        |\n| iconComponents    | custom icon components                  | object   | ant design icons (default)                     |\n| onChange          | callback when tree state changes        | function | console.log (default)                          |\n| onNameClick       | callback when click treenode name       | function | open treenode inline toolbox (default)         |\n| indentPixels      | ident pixels of 1x level treenode       | number   | 30 (default)                                   |\n| showCheckbox      | show check box?                         | bool     | true (default) | false                         |\n| readOnly          | readOnly mode? can't click/check node   | bool     | false (default) | true                       |\n\n---\n## Bugs? Questions? Contributions?\nFeel free to [open an issue](https://github.com/shunjizhan/react-folder-tree/issues), or create a pull request!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunjizhan%2Freact-folder-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshunjizhan%2Freact-folder-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunjizhan%2Freact-folder-tree/lists"}