-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Get basic structure for development set up
- Loading branch information
0 parents
commit 5843280
Showing
11 changed files
with
13,682 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"presets": [ | ||
["env", { | ||
"targets": { | ||
"browsers": ["last 2 versions", "ie >= 9"] | ||
} | ||
}], | ||
"react" | ||
], | ||
"plugins": [ | ||
"transform-object-rest-spread", | ||
"react-hot-loader/babel" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"extends": ["airbnb", "prettier", "prettier/react"], | ||
"env": { | ||
"browser": true, | ||
"jest": true | ||
}, | ||
"rules": { | ||
"react/jsx-filename-extension": 0, | ||
"react/prefer-stateless-function": 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
node_modules | ||
npm-debug.log | ||
yarn.lock | ||
coverage | ||
cc-test-reporter | ||
|
||
# Editor and other tmp files | ||
*.swp | ||
*.un~ | ||
*.iml | ||
*.ipr | ||
*.iws | ||
*.sublime-* | ||
.idea/ | ||
*.DS_Store | ||
|
||
# Build directories (Will be preserved by npm) | ||
dist | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,297 @@ | ||
import React, { Component } from 'react'; | ||
import SortableTree, { toggleExpandedForAll } from 'react-sortable-tree'; | ||
import CustomNodeRenderer from '../index'; | ||
|
||
const maxDepth = 5; | ||
|
||
class App extends Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
const renderDepthTitle = ({ path }) => `Depth: ${path.length}`; | ||
|
||
this.state = { | ||
searchString: '', | ||
searchFocusIndex: 0, | ||
searchFoundCount: null, | ||
treeData: [ | ||
{ | ||
title: '`title`', | ||
subtitle: '`subtitle`', | ||
expanded: true, | ||
children: [ | ||
{ | ||
title: 'Child Node', | ||
subtitle: 'Defined in `children` array belonging to parent', | ||
}, | ||
{ | ||
title: 'Nested structure is rendered virtually', | ||
subtitle: ( | ||
<span> | ||
The tree uses | ||
<a href="https://github.com/bvaughn/react-virtualized"> | ||
react-virtualized | ||
</a> | ||
and the relationship lines are more of a visual trick. | ||
</span> | ||
), | ||
}, | ||
], | ||
}, | ||
{ | ||
expanded: true, | ||
title: 'Any node can be the parent or child of any other node', | ||
children: [ | ||
{ | ||
expanded: true, | ||
title: 'Chicken', | ||
children: [{ title: 'Egg' }], | ||
}, | ||
], | ||
}, | ||
{ | ||
title: 'Button(s) can be added to the node', | ||
subtitle: | ||
'Node info is passed when generating so you can use it in your onClick handler', | ||
}, | ||
{ | ||
title: 'Show node children by setting `expanded`', | ||
subtitle: ({ node }) => | ||
`expanded: ${node.expanded ? 'true' : 'false'}`, | ||
children: [ | ||
{ | ||
title: 'Bruce', | ||
subtitle: ({ node }) => | ||
`expanded: ${node.expanded ? 'true' : 'false'}`, | ||
children: [{ title: 'Bruce Jr.' }, { title: 'Brucette' }], | ||
}, | ||
], | ||
}, | ||
{ | ||
title: 'Advanced', | ||
subtitle: 'Settings, behavior, etc.', | ||
children: [ | ||
{ | ||
title: ( | ||
<div> | ||
<div | ||
style={{ | ||
backgroundColor: 'gray', | ||
display: 'inline-block', | ||
borderRadius: 10, | ||
color: '#FFF', | ||
padding: '0 5px', | ||
}} | ||
> | ||
Any Component | ||
</div> | ||
can be used for `title` | ||
</div> | ||
), | ||
}, | ||
{ | ||
expanded: true, | ||
title: 'Limit nesting with `maxDepth`', | ||
subtitle: `It's set to ${maxDepth} for this example`, | ||
children: [ | ||
{ | ||
expanded: true, | ||
title: renderDepthTitle, | ||
children: [ | ||
{ | ||
expanded: true, | ||
title: renderDepthTitle, | ||
children: [ | ||
{ title: renderDepthTitle }, | ||
{ | ||
title: ({ path }) => | ||
path.length >= maxDepth | ||
? 'This cannot be dragged deeper' | ||
: 'This can be dragged deeper', | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
{ | ||
title: | ||
'Disable dragging on a per-node basis with the `canDrag` prop', | ||
subtitle: 'Or set it to false to disable all dragging.', | ||
noDragging: true, | ||
}, | ||
{ | ||
title: 'You cannot give this children', | ||
subtitle: | ||
'Dropping is prevented via the `canDrop` API using `nextParent`', | ||
noChildren: true, | ||
}, | ||
{ | ||
title: | ||
'When node contents are really long, it will cause a horizontal scrollbar' + | ||
' to appear. Deeply nested elements will also trigger the scrollbar.', | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
this.updateTreeData = this.updateTreeData.bind(this); | ||
this.expandAll = this.expandAll.bind(this); | ||
this.collapseAll = this.collapseAll.bind(this); | ||
} | ||
|
||
updateTreeData(treeData) { | ||
this.setState({ treeData }); | ||
} | ||
|
||
expand(expanded) { | ||
this.setState({ | ||
treeData: toggleExpandedForAll({ | ||
treeData: this.state.treeData, | ||
expanded, | ||
}), | ||
}); | ||
} | ||
|
||
expandAll() { | ||
this.expand(true); | ||
} | ||
|
||
collapseAll() { | ||
this.expand(false); | ||
} | ||
|
||
render() { | ||
const { | ||
treeData, | ||
searchString, | ||
searchFocusIndex, | ||
searchFoundCount, | ||
} = this.state; | ||
|
||
const alertNodeInfo = ({ node, path, treeIndex }) => { | ||
const objectString = Object.keys(node) | ||
.map(k => (k === 'children' ? 'children: Array' : `${k}: '${node[k]}'`)) | ||
.join(',\n '); | ||
|
||
global.alert( | ||
'Info passed to the button generator:\n\n' + | ||
`node: {\n ${objectString}\n},\n` + | ||
`path: [${path.join(', ')}],\n` + | ||
`treeIndex: ${treeIndex}` | ||
); | ||
}; | ||
|
||
const selectPrevMatch = () => | ||
this.setState({ | ||
searchFocusIndex: | ||
searchFocusIndex !== null | ||
? (searchFoundCount + searchFocusIndex - 1) % searchFoundCount | ||
: searchFoundCount - 1, | ||
}); | ||
|
||
const selectNextMatch = () => | ||
this.setState({ | ||
searchFocusIndex: | ||
searchFocusIndex !== null | ||
? (searchFocusIndex + 1) % searchFoundCount | ||
: 0, | ||
}); | ||
|
||
const isVirtualized = true; | ||
const treeContainerStyle = isVirtualized ? { height: 450 } : {}; | ||
|
||
return ( | ||
<div> | ||
<h3>Demo</h3> | ||
<button onClick={this.expandAll}>Expand All</button> | ||
<button onClick={this.collapseAll}>Collapse All</button> | ||
| ||
<form | ||
style={{ display: 'inline-block' }} | ||
onSubmit={event => { | ||
event.preventDefault(); | ||
}} | ||
> | ||
<label htmlFor="find-box"> | ||
Search: | ||
<input | ||
id="find-box" | ||
type="text" | ||
value={searchString} | ||
onChange={event => | ||
this.setState({ searchString: event.target.value })} | ||
/> | ||
</label> | ||
|
||
<button | ||
type="button" | ||
disabled={!searchFoundCount} | ||
onClick={selectPrevMatch} | ||
> | ||
< | ||
</button> | ||
|
||
<button | ||
type="submit" | ||
disabled={!searchFoundCount} | ||
onClick={selectNextMatch} | ||
> | ||
> | ||
</button> | ||
|
||
<span> | ||
| ||
{searchFoundCount > 0 ? searchFocusIndex + 1 : 0} | ||
/ | ||
{searchFoundCount || 0} | ||
</span> | ||
</form> | ||
<div style={treeContainerStyle}> | ||
<SortableTree | ||
treeData={treeData} | ||
onChange={this.updateTreeData} | ||
onMoveNode={({ node, treeIndex, path }) => | ||
global.console.debug( | ||
'node:', | ||
node, | ||
'treeIndex:', | ||
treeIndex, | ||
'path:', | ||
path | ||
)} | ||
maxDepth={maxDepth} | ||
searchQuery={searchString} | ||
searchFocusOffset={searchFocusIndex} | ||
canDrag={({ node }) => !node.noDragging} | ||
canDrop={({ nextParent }) => !nextParent || !nextParent.noChildren} | ||
searchFinishCallback={matches => | ||
this.setState({ | ||
searchFoundCount: matches.length, | ||
searchFocusIndex: | ||
matches.length > 0 ? searchFocusIndex % matches.length : 0, | ||
})} | ||
isVirtualized={isVirtualized} | ||
generateNodeProps={rowInfo => ({ | ||
buttons: [ | ||
<button | ||
style={{ | ||
verticalAlign: 'middle', | ||
}} | ||
onClick={() => alertNodeInfo(rowInfo)} | ||
> | ||
ℹ | ||
</button>, | ||
], | ||
})} | ||
nodeContentRenderer={CustomNodeRenderer} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<!DOCTYPE html> | ||
<html lang="en-us"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>React Sortable Tree</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="apple-touch-icon" sizes="180x180" href="static/apple-touch-icon.png"> | ||
<link rel="icon" type="image/png" href="static/favicon-32x32.png" sizes="32x32"> | ||
<link rel="icon" type="image/png" href="static/favicon-16x16.png" sizes="16x16"> | ||
<link rel="mask-icon" href="static/safari-pinned-tab.svg" color="#de7a32"> | ||
<link rel="shortcut icon" href="static/favicon.ico"> | ||
<meta name="theme-color" content="#ffffff"> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import { AppContainer } from 'react-hot-loader'; // eslint-disable-line import/no-extraneous-dependencies | ||
|
||
const rootEl = document.getElementById('app'); | ||
const render = Component => { | ||
ReactDOM.render( | ||
<AppContainer> | ||
<Component /> | ||
</AppContainer>, | ||
rootEl | ||
); | ||
}; | ||
|
||
/* eslint-disable global-require, import/newline-after-import */ | ||
render(require('./app').default); | ||
if (module.hot) | ||
module.hot.accept('./app', () => render(require('./app').default)); | ||
/* eslint-enable global-require, import/newline-after-import */ |
Oops, something went wrong.