@marciocamello/react-sortable-tree
Version:
Drag-and-drop sortable component for nested data and hierarchies
156 lines (141 loc) • 4.57 kB
JavaScript
import React, { Component } from 'react'
import SortableTree from '../src'
// In your own app, you would need to use import styles once in the app
// import 'react-sortable-tree/styles.css';
export default class App extends Component {
constructor(props) {
super(props)
const title = 'Hay'
// For generating a haystack (you probably won't need to do this)
const getStack = (left, hasNeedle = false) => {
if (left === 0) {
return hasNeedle ? { title: 'Needle' } : { title }
}
return {
title,
children: [
{
title,
children: [getStack(left - 1, hasNeedle && left % 2), { title }],
},
{ title },
{
title,
children: [
{ title },
getStack(left - 1, hasNeedle && (left + 1) % 2),
],
},
],
}
}
this.state = {
searchString: '',
searchFocusIndex: 0,
searchFoundCount: null,
treeData: [
{
title: 'Haystack',
children: [
getStack(3, true),
getStack(3),
{ title },
getStack(2, true),
],
},
],
}
}
render() {
const { searchString, searchFocusIndex, searchFoundCount } = this.state
// Case insensitive search of `node.title`
const customSearchMethod = ({ node, searchQuery }) =>
searchQuery &&
node.title.toLowerCase().indexOf(searchQuery.toLowerCase()) > -1
const selectPrevMatch = () =>
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFoundCount + searchFocusIndex - 1) % searchFoundCount
: searchFoundCount - 1,
})
const selectNextMatch = () =>
this.setState({
searchFocusIndex:
searchFocusIndex !== null
? (searchFocusIndex + 1) % searchFoundCount
: 0,
})
return (
<div>
<h2>Find the needle!</h2>
<form
style={{ display: 'inline-block' }}
onSubmit={(event) => {
event.preventDefault()
}}>
<input
id="find-box"
type="text"
placeholder="Search..."
style={{ fontSize: '1rem' }}
value={searchString}
onChange={(event) =>
this.setState({ searchString: event.target.value })
}
/>
<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={{ height: 300 }}>
<SortableTree
treeData={this.state.treeData}
onChange={(treeData) => this.setState({ treeData })}
//
// Custom comparison for matching during search.
// This is optional, and defaults to a case sensitive search of
// the title and subtitle values.
// see `defaultSearchMethod` in https://github.com/frontend-collective/react-sortable-tree/blob/master/src/utils/default-handlers.js
searchMethod={customSearchMethod}
//
// The query string used in the search. This is required for searching.
searchQuery={searchString}
//
// When matches are found, this property lets you highlight a specific
// match and scroll to it. This is optional.
searchFocusOffset={searchFocusIndex}
//
// This callback returns the matches from the search,
// including their `node`s, `treeIndex`es, and `path`s
// Here I just use it to note how many matches were found.
// This is optional, but without it, the only thing searches
// do natively is outline the matching nodes.
searchFinishCallback={(matches) =>
this.setState({
searchFoundCount: matches.length,
searchFocusIndex:
matches.length > 0 ? searchFocusIndex % matches.length : 0,
})
}
/>
</div>
</div>
)
}
}