Skip to content

Commit 75edd7a

Browse files
committed
try out react-sortable-hoc
1 parent a09556d commit 75edd7a

File tree

4 files changed

+145
-90
lines changed

4 files changed

+145
-90
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"dependencies": {
3535
"react-dnd": "^2.1.4",
3636
"react-dnd-html5-backend": "^2.1.2",
37+
"react-sortable-hoc": "0.0.7",
3738
"react-virtualized": "^7.17.0"
3839
},
3940
"peerDependencies": {

src/node-renderer-default.js

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ if (getIEVersion < 10) {
1717
const NodeRendererDefault = ({
1818
scaffoldBlockPxWidth,
1919
toggleChildrenVisibility,
20-
connectDragPreview,
21-
connectDragSource,
22-
isDragging,
23-
isOver,
24-
canDrop,
20+
// connectDragPreview,
21+
// connectDragSource,
22+
// isDragging,
23+
// isOver,
24+
// canDrop,
25+
sortableHandle,
2526
node,
2627
path,
2728
treeIndex,
@@ -49,20 +50,23 @@ const NodeRendererDefault = ({
4950
</div>
5051
</div>
5152
);
52-
} else if (isDragging) {
53-
handle = (<div className={styles.loadingHandle} />);
53+
// } else if (isDragging) {
54+
// handle = (<div className={styles.loadingHandle} />);
5455
} else {
5556
let myStyle = {};
56-
if (isOver && canDrop) {
57-
myStyle = { backgroundColor: 'lightblue' };
58-
}
57+
// if (isOver && canDrop) {
58+
// myStyle = { backgroundColor: 'lightblue' };
59+
// }
5960

6061
// Show the handle used to initiate a drag-and-drop
61-
handle = connectDragSource((
62-
<div className={styles.moveHandle} style={myStyle} />
63-
), { dropEffect: 'copy' });
62+
// handle = connectDragSource((
63+
// <div className={styles.moveHandle} style={myStyle} />
64+
// ), { dropEffect: 'copy' });
65+
handle = <div className={styles.moveHandle} style={myStyle} />;
6466
}
6567

68+
const Handle = sortableHandle(() => handle);
69+
6670
return (
6771
<div style={{ height: '100%' }}>
6872
{toggleChildrenVisibility && node.children && node.children.length > 0 && (
@@ -74,37 +78,35 @@ const NodeRendererDefault = ({
7478
)}
7579

7680
{/* Set the row preview to be used during drag and drop */}
77-
{connectDragPreview(
78-
<div className={styles.row + (isDragging ? ` ${styles.rowOriginWhileDragging}` : '')}>
79-
{handle}
80-
81-
<div className={styles.rowContents}>
82-
<div className={styles.rowLabel}>
83-
<span
84-
className={styles.rowTitle +
85-
(node.subtitle ? ` ${styles.rowTitleWithSubtitle}` : '')
86-
}
87-
>
88-
{node.title}
89-
</span>
81+
<div className={styles.row}>
82+
<Handle />
9083

91-
{node.subtitle &&
92-
<span className={styles.rowSubtitle}>
93-
{node.subtitle}
94-
</span>
84+
<div className={styles.rowContents}>
85+
<div className={styles.rowLabel}>
86+
<span
87+
className={styles.rowTitle +
88+
(node.subtitle ? ` ${styles.rowTitleWithSubtitle}` : '')
9589
}
96-
</div>
90+
>
91+
{node.title}
92+
</span>
93+
94+
{node.subtitle &&
95+
<span className={styles.rowSubtitle}>
96+
{node.subtitle}
97+
</span>
98+
}
99+
</div>
97100

98-
<div className={styles.rowToolbar}>
99-
{buttons && buttons.map((btn, index) => (
100-
<div key={index} className={styles.toolbarButton}>
101-
{btn}
102-
</div>
103-
))}
104-
</div>
101+
<div className={styles.rowToolbar}>
102+
{buttons && buttons.map((btn, index) => (
103+
<div key={index} className={styles.toolbarButton}>
104+
{btn}
105+
</div>
106+
))}
105107
</div>
106-
</div>
107-
)}
108+
</div>
109+
</div>
108110
</div>
109111
);
110112
};
@@ -119,14 +121,15 @@ NodeRendererDefault.propTypes = {
119121
toggleChildrenVisibility: PropTypes.func,
120122
buttons: PropTypes.arrayOf(PropTypes.node),
121123

124+
sortableHandle: PropTypes.func.isRequired,
122125
// Drag and drop API functions
123126
// Drag source
124-
connectDragPreview: PropTypes.func.isRequired,
125-
connectDragSource: PropTypes.func.isRequired,
126-
isDragging: PropTypes.bool.isRequired,
127-
// Drop target
128-
isOver: PropTypes.bool.isRequired,
129-
canDrop: PropTypes.bool.isRequired,
127+
// connectDragPreview: PropTypes.func.isRequired,
128+
// connectDragSource: PropTypes.func.isRequired,
129+
// isDragging: PropTypes.bool.isRequired,
130+
// // Drop target
131+
// isOver: PropTypes.bool.isRequired,
132+
// canDrop: PropTypes.bool.isRequired,
130133
};
131134

132135
export default NodeRendererDefault;

src/react-sortable-tree.js

Lines changed: 84 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
*/
66

77
import React, { Component, PropTypes } from 'react';
8+
import {
9+
SortableContainer as sortableContainer,
10+
SortableElement as sortableElement,
11+
SortableHandle as sortableHandle,
12+
} from 'react-sortable-hoc';
813
import { AutoSizer, VirtualScroll } from 'react-virtualized';
914
import 'react-virtualized/styles.css';
1015
import TreeNode from './tree-node';
@@ -15,10 +20,10 @@ import {
1520
removeNodeAtPath,
1621
addNodeUnderParentPath,
1722
} from './utils/tree-data-utils';
18-
import {
19-
dndWrapRoot,
20-
dndWrapSource,
21-
} from './utils/drag-and-drop-utils';
23+
// import {
24+
// dndWrapRoot,
25+
// dndWrapSource,
26+
// } from './utils/drag-and-drop-utils';
2227
import styles from './react-sortable-tree.scss';
2328

2429
function defaultGetNodeKey({ node: _node, treeIndex }) {
@@ -66,11 +71,14 @@ class ReactSortableTree extends Component {
6671
this.toggleChildrenVisibility = (
6772
props.toggleChildrenVisibility || defaultToggleChildrenVisibility
6873
).bind(this);
69-
this.nodeContentRenderer = dndWrapSource(
74+
this.nodeContentRenderer = /* dndWrapSource */(
7075
props.nodeContentRenderer ||
7176
require('./node-renderer-default').default // eslint-disable-line global-require
7277
);
7378

79+
this.rowRenderer = sortableElement(this.renderRow);
80+
this.listRenderer = sortableContainer(this.renderList);
81+
7482
this.state = {
7583
draggingTreeData: null,
7684
rows: this.getRows(props.treeData),
@@ -144,6 +152,11 @@ class ReactSortableTree extends Component {
144152
});
145153
}
146154

155+
// return this.setState({
156+
// draggingTreeData: null,
157+
// rows: this.getRows(this.props.treeData),
158+
// });
159+
147160
this.moveNode({
148161
node,
149162
path,
@@ -191,38 +204,81 @@ class ReactSortableTree extends Component {
191204
}
192205

193206
render() {
207+
const ListRenderer = this.listRenderer;
194208
const {
195209
style,
196210
className,
197-
rowHeight,
198211
} = this.props;
199-
const { rows } = this.state;
212+
213+
const listProps = {
214+
rows: this.state.rows,
215+
RowRenderer: this.rowRenderer,
216+
rowHeight: this.props.rowHeight,
217+
};
218+
219+
const rowProps = {
220+
toggleChildrenVisibility: this.props.toggleChildrenVisibility,
221+
scaffoldBlockPxWidth: this.props.scaffoldBlockPxWidth,
222+
generateNodeProps: this.props.generateNodeProps,
223+
NodeContentRenderer: this.nodeContentRenderer,
224+
};
200225

201226
return (
202227
<div
203228
className={styles.tree + (className ? ` ${className}` : '')}
204229
style={{ height: '100%', ...style }}
205230
>
206-
<AutoSizer>
207-
{({height, width}) => (
208-
<VirtualScroll
209-
className={styles.virtualScrollOverride}
210-
width={width}
211-
height={height}
212-
rowCount={rows.length}
213-
estimatedRowSize={rowHeight}
214-
rowHeight={rowHeight}
215-
rowRenderer={({ index }) => this.renderRow(rows[index], index)}
216-
/>
217-
)}
218-
</AutoSizer>
231+
<ListRenderer
232+
listProps={listProps}
233+
rowProps={rowProps}
234+
useDragHandle
235+
/>
219236
</div>
220237
);
221238
}
222239

223-
renderRow({ node, path, lowerSiblingCounts }, treeIndex) {
224-
const NodeContentRenderer = this.nodeContentRenderer;
225-
const nodeProps = !this.props.generateNodeProps ? {} : this.props.generateNodeProps({
240+
renderList({
241+
listProps: {
242+
rows,
243+
RowRenderer,
244+
rowHeight,
245+
},
246+
rowProps,
247+
}) {
248+
return (
249+
<AutoSizer>
250+
{({height, width}) => (
251+
<VirtualScroll
252+
className={styles.virtualScrollOverride}
253+
width={width}
254+
height={height}
255+
rowCount={rows.length}
256+
estimatedRowSize={rowHeight}
257+
rowHeight={rowHeight}
258+
rowRenderer={({ index }) => (
259+
<RowRenderer
260+
value={rows[index]}
261+
index={index}
262+
rowProps={rowProps}
263+
/>
264+
)}
265+
/>
266+
)}
267+
</AutoSizer>
268+
);
269+
}
270+
271+
renderRow({
272+
value: { node, path, lowerSiblingCounts },
273+
index: treeIndex,
274+
rowProps: {
275+
toggleChildrenVisibility,
276+
scaffoldBlockPxWidth,
277+
generateNodeProps,
278+
NodeContentRenderer,
279+
},
280+
}) {
281+
const nodeProps = !generateNodeProps ? {} : generateNodeProps({
226282
node,
227283
path,
228284
lowerSiblingCounts,
@@ -234,18 +290,16 @@ class ReactSortableTree extends Component {
234290
treeIndex={treeIndex}
235291
path={path}
236292
lowerSiblingCounts={lowerSiblingCounts}
237-
scaffoldBlockPxWidth={this.props.scaffoldBlockPxWidth}
238-
dragHover={this.dragHover}
293+
scaffoldBlockPxWidth={scaffoldBlockPxWidth}
239294
>
240295
<NodeContentRenderer
241296
node={node}
242297
path={path}
243298
lowerSiblingCounts={lowerSiblingCounts}
244299
treeIndex={treeIndex}
245-
startDrag={this.startDrag}
246-
endDrag={this.endDrag}
247-
toggleChildrenVisibility={this.toggleChildrenVisibility}
248-
scaffoldBlockPxWidth={this.props.scaffoldBlockPxWidth}
300+
toggleChildrenVisibility={toggleChildrenVisibility}
301+
scaffoldBlockPxWidth={scaffoldBlockPxWidth}
302+
sortableHandle={sortableHandle}
249303
{...nodeProps}
250304
/>
251305
</TreeNode>
@@ -286,4 +340,4 @@ ReactSortableTree.defaultProps = {
286340
loadCollapsedLazyChildren: false,
287341
};
288342

289-
export default dndWrapRoot(ReactSortableTree);
343+
export default /* dndWrapRoot( */ReactSortableTree/* ) */;

src/tree-node.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import React, { PropTypes, Children, cloneElement } from 'react';
2-
import { dndWrapTarget } from './utils/drag-and-drop-utils';
1+
import React, { PropTypes, /* Children, cloneElement */ } from 'react';
2+
// import { dndWrapTarget } from './utils/drag-and-drop-utils';
33
import styles from './tree-node.scss';
44

55
const TreeNode = ({
66
children,
77
treeIndex,
88
scaffoldBlockPxWidth,
99
lowerSiblingCounts,
10-
connectDropTarget,
11-
isOver,
12-
canDrop,
10+
// connectDropTarget,
11+
// isOver,
12+
// canDrop,
1313
}) => {
1414
// Construct the scaffold representing the structure of the tree
1515
const scaffoldBlockCount = lowerSiblingCounts.length;
@@ -69,18 +69,15 @@ const TreeNode = ({
6969
);
7070
});
7171

72-
return connectDropTarget(
72+
return /* connectDropTarget */(
7373
<li className={styles.node}>
7474
{scaffold}
7575

7676
<div
7777
className={styles.nodeContent}
7878
style={{ left: scaffoldBlockPxWidth * scaffoldBlockCount }}
7979
>
80-
{Children.map(children, child => cloneElement(child, {
81-
isOver,
82-
canDrop,
83-
}))}
80+
{children}
8481
</div>
8582
</li>
8683
);
@@ -94,9 +91,9 @@ TreeNode.propTypes = {
9491
lowerSiblingCounts: PropTypes.array.isRequired,
9592

9693
// Drop target
97-
connectDropTarget: PropTypes.func.isRequired,
98-
isOver: PropTypes.bool.isRequired,
99-
canDrop: PropTypes.bool.isRequired,
94+
// connectDropTarget: PropTypes.func.isRequired,
95+
// isOver: PropTypes.bool.isRequired,
96+
// canDrop: PropTypes.bool.isRequired,
10097
};
10198

102-
export default dndWrapTarget(TreeNode);
99+
export default /* dndWrapTarget */(TreeNode);

0 commit comments

Comments
 (0)