1.1.0 • Published 5 years ago
react-tree-file-system v1.1.0
react-tree-file-system
A basic tree file system that allows customisation
- custom CSS and classNames
- drag and drop available
- demo available
1 Demo
Version 1.1.0
Version 1.0.6
You can also try out here
2 Get Started
# To download, either
npm install --save react-tree-file-system
# or
yarn add react-tree-file-system
In your code
import Tree from 'react-tree-file-system';
// import stylesheet
import 'react-tree-file-system/index.css';
Uncontrolled component
- you can toggle folder to open or close by using recursion
const recursiveSetState = (tree, indexes, currIndex, key, value) => {
const dupTree= tree.slice();
const getIndex = indexes[currIndex];
if (currIndex === indexes.length - 1) {
dupTree[getIndex][key] = value;
return tree;
}
dupTree[getIndex].children = recursiveSetState(
(dupTree[getIndex].children || []).slice(0),
indexes,
currIndex + 1, key, value
);
return dupTree;
}
// ...
class YourClass extends React.Component {
constructor(props) {
super(props);
this.state = {
treeValue: [
{
title: 'folder name'
type: 'folder',
children: [
{
title: 'child 1'
},
{
title: 'child 2'
},
{
title: 'child 3'
}
]
}
]
}
}
render() {
return (
// ...
<Tree
value={this.state.treeValue}
folderOnClick={(_, indexes, state) => {
this.setState(prevState => {
return {
treeValue: recursiveSetState(prevState.treeValue, indexes, 0, 'isOpen', state);
}
});
}}
/>
// ...
)
}
}
- you can support on drag with recursion
const recursivelySetChild = (tree, toIndexes, currIndex, extractData) => {
const dupTree= tree.slice();
const getIndex = toIndexes[currIndex];
if (currIndex === toIndexes.length - 1) {
dupTree[getIndex].children.push(extractData);
return tree;
}
dupTree[getIndex].children = recursivelySetChild((dupTree[getIndex].children || []).slice(0), toIndexes, currIndex + 1, extractData);
return dupTree;
}
const getRecursiveItem = (tree, fromIndexes, currIndex) => {
const dupTree = tree.slice(0);
const getIndex = fromIndexes[currIndex];
if(currIndex === fromIndexes.length - 1) {
const child = dupTree.filter((_, i) => i === getIndex);
return child[0];
}
return getRecursiveItem((dupTree[getIndex].children || []).slice(0), fromIndexes, currIndex + 1);
}
const popRecursiveItem = (tree, fromIndexes, currIndex) => {
const dupTree = tree.slice(0);
const getIndex = fromIndexes[currIndex];
if(currIndex === fromIndexes.length - 1) {
const filtered = dupTree.filter((_, i) => i !== getIndex);
return filtered;
}
const children = popRecursiveItem((dupTree[getIndex].children || []).slice(0), fromIndexes, currIndex + 1);
dupTree[getIndex].children = children;
return dupTree;
}
// ...
class YourClass extends React.Component {
constructor(props) {
super(props);
this.state = {
treeValue: [
{
title: 'folder name'
type: 'folder',
children: [
{
title: 'child 1'
},
{
title: 'child 2'
},
{
title: 'child 3'
}
]
}
]
}
}
render() {
return (
// ...
<Tree
value={this.state.treeValue}
onDrag={(fromIndexes, toIndexes) => {
this.setState(prevState => {
const extractData = getRecursiveItem(prevState.defaultTree, fromIndexes, 0);
const extraData = recursivelySetChild(prevState.defaultTree, toIndexes, 0, extractData);
const newData = popRecursiveItem(prevState.defaultTree, fromIndexes, 0);
return {
defaultTree: newData
}
})
}}
/>
// ...
)
}
}
4 Tree Structure
// Node
interface Node {
title: string,
isOpen?: boolean,
// isLocked?: boolean, // No support yet
// isHidden?: boolean, // No support yet
children?: Node[],
folderIcon?: React.Element,
fileIcon?: React.Element,
style?: React.CSSProperties,
className?: string,
// able to add anything here
}
// Example
[
{
title: 'main', // what is displayed
isOpen: false, // optional
type: 'folder',
folderIcon: <FolderIcon /> // optional
children: [
{
title: 'Child 1',
},
{
title: 'Readme.md',
fileIcon: <FileIcon />, // optional
text: 'demo text'
},
]
},
// ... repeat Node
]
5 API
Property | Description | Type | Default |
---|---|---|---|
value | The Tree structure given in point 4 | Node[] | undefined |
fileOnClick | Called when file is clicked | (event, indexes: number[], value: Node) => void | undefined |
folderOnClick | Called when folder is clicked | (event, indexes: number[], state: boolean, value: Node) => void | undefined |
onDrop | Called when something is dragged on folder Replace onDrag | (event, fromIndexes, toIndexes) => void | undefined |
onDrag | Called when something is dragged on folder Depreciated | (event, fromIndexes, toIndexes) => void | undefined |
folderIcon | Replace the default folder icon | JSX.Element | undefined |
fileIcon | Replace the default file icon | JSX.Element | undefined |
style | customize the general style | React.CSSProperties | undefined |
isDraggable | customize the general style | React.CSSProperties | false |
selected | Enable highlighting of cell clicked. Basically just store the indexes as indexes.join(',') | string | undefined |
selectedClassName | customize the highlighted style with your own className | string | undefined |