Skip to content

Commit 2caa9d1

Browse files
committed
feat: add onDragStateChanged callback
Thanks to @wuweiweiwu for the contribution! onDragStateChanged is called when dragging begins and ends, so you can easily track the current state of dragging.
2 parents 006ea08 + 588a95f commit 2caa9d1

File tree

6 files changed

+446
-1
lines changed

6 files changed

+446
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ getNodeKey<br/>_(recommended)_ | func | Specify the unique key used to iden
4848
generateNodeProps | func | Generate an object with additional props to be passed to the node renderer. Use this for adding buttons via the `buttons` key, or additional `style` / `className` settings.<div>`({ node: object, path: number[] or string[], treeIndex: number, lowerSiblingCounts: number[], isSearchMatch: bool, isSearchFocus: bool }): object`</div>
4949
onMoveNode | func | Called after node move operation. <div>`({ treeData: object[], node: object, prevPath: number[] or string[], prevTreeIndex: number, nextPath: number[] or string[], nextTreeIndex: number }): void`</div>
5050
onVisibilityToggle | func | Called after children nodes collapsed or expanded. <div>`({ treeData: object[], node: object, expanded: bool, path: number[] or string[] }): void`</div>
51+
onDragStateChanged | func | Called when a drag is initiated or ended. <div>`({ isDragging: bool, draggedNode: object }): void`</div>
5152
maxDepth | number | Maximum depth nodes can be inserted at. Defaults to infinite.
5253
canDrag | func or bool | Return false from callback to prevent node from dragging, by hiding the drag handle. Set prop to `false` to disable dragging on all nodes. Defaults to `true`. <div>`({ node: object, path: number[] or string[], treeIndex: number, lowerSiblingCounts: number[], isSearchMatch: bool, isSearchFocus: bool }): bool`</div>
5354
canDrop | func | Return false to prevent node from dropping in the given location. <div>`({ node: object, prevPath: number[] or string[], prevParent: object, prevTreeIndex: number, nextPath: number[] or string[], nextParent: object, nextTreeIndex: number }): bool`</div>

examples/storybooks/__snapshots__/storyshots.test.js.snap

+314
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,320 @@ exports[`Storyshots Basics Add and remove nodes programmatically 1`] = `
19611961
</div>
19621962
`;
19631963

1964+
exports[`Storyshots Basics Callbacks 1`] = `
1965+
<div>
1966+
<div>
1967+
Open your console to see callback parameter info
1968+
<div
1969+
style={
1970+
Object {
1971+
"height": 300,
1972+
}
1973+
}
1974+
>
1975+
<div
1976+
className="tree"
1977+
style={
1978+
Object {
1979+
"height": "100%",
1980+
}
1981+
}
1982+
>
1983+
<div>
1984+
<div
1985+
aria-label="grid"
1986+
aria-readonly={true}
1987+
className="ReactVirtualized__Grid ReactVirtualized__List virtualScrollOverride"
1988+
id={undefined}
1989+
onScroll={[Function]}
1990+
role="grid"
1991+
style={
1992+
Object {
1993+
"WebkitOverflowScrolling": "touch",
1994+
"boxSizing": "border-box",
1995+
"direction": "ltr",
1996+
"height": 99999,
1997+
"overflowX": "hidden",
1998+
"overflowY": "hidden",
1999+
"position": "relative",
2000+
"width": 200,
2001+
"willChange": "transform",
2002+
}
2003+
}
2004+
tabIndex={0}
2005+
>
2006+
<div
2007+
className="ReactVirtualized__Grid__innerScrollContainer"
2008+
role="rowgroup"
2009+
style={
2010+
Object {
2011+
"height": 186,
2012+
"maxHeight": 186,
2013+
"maxWidth": 200,
2014+
"overflow": "hidden",
2015+
"pointerEvents": "",
2016+
"position": "relative",
2017+
"width": "auto",
2018+
}
2019+
}
2020+
>
2021+
<div
2022+
className="node"
2023+
style={
2024+
Object {
2025+
"height": 62,
2026+
"left": 0,
2027+
"position": "absolute",
2028+
"top": 0,
2029+
"width": "100%",
2030+
}
2031+
}
2032+
>
2033+
<div
2034+
className="lineBlock lineHalfHorizontalRight lineHalfVerticalBottom"
2035+
style={
2036+
Object {
2037+
"width": 44,
2038+
}
2039+
}
2040+
/>
2041+
<div
2042+
className="nodeContent"
2043+
style={
2044+
Object {
2045+
"left": 44,
2046+
}
2047+
}
2048+
>
2049+
<div
2050+
style={
2051+
Object {
2052+
"height": "100%",
2053+
}
2054+
}
2055+
>
2056+
<div>
2057+
<button
2058+
aria-label="Collapse"
2059+
className="collapseButton"
2060+
onClick={[Function]}
2061+
style={
2062+
Object {
2063+
"left": -22,
2064+
}
2065+
}
2066+
type="button"
2067+
/>
2068+
<div
2069+
className="lineChildren"
2070+
style={
2071+
Object {
2072+
"width": 44,
2073+
}
2074+
}
2075+
/>
2076+
</div>
2077+
<div
2078+
className="rowWrapper"
2079+
>
2080+
<div
2081+
className="row"
2082+
style={
2083+
Object {
2084+
"opacity": 1,
2085+
}
2086+
}
2087+
>
2088+
<div
2089+
className="moveHandle"
2090+
/>
2091+
<div
2092+
className="rowContents"
2093+
>
2094+
<div
2095+
className="rowLabel"
2096+
>
2097+
<span
2098+
className="rowTitle"
2099+
>
2100+
A
2101+
</span>
2102+
</div>
2103+
<div
2104+
className="rowToolbar"
2105+
/>
2106+
</div>
2107+
</div>
2108+
</div>
2109+
</div>
2110+
</div>
2111+
</div>
2112+
<div
2113+
className="node"
2114+
style={
2115+
Object {
2116+
"height": 62,
2117+
"left": 0,
2118+
"position": "absolute",
2119+
"top": 62,
2120+
"width": "100%",
2121+
}
2122+
}
2123+
>
2124+
<div
2125+
className="lineBlock lineFullVertical"
2126+
style={
2127+
Object {
2128+
"width": 44,
2129+
}
2130+
}
2131+
/>
2132+
<div
2133+
className="lineBlock lineHalfVerticalTop lineHalfHorizontalRight"
2134+
style={
2135+
Object {
2136+
"width": 44,
2137+
}
2138+
}
2139+
/>
2140+
<div
2141+
className="nodeContent"
2142+
style={
2143+
Object {
2144+
"left": 88,
2145+
}
2146+
}
2147+
>
2148+
<div
2149+
style={
2150+
Object {
2151+
"height": "100%",
2152+
}
2153+
}
2154+
>
2155+
<div
2156+
className="rowWrapper"
2157+
>
2158+
<div
2159+
className="row"
2160+
style={
2161+
Object {
2162+
"opacity": 1,
2163+
}
2164+
}
2165+
>
2166+
<div
2167+
className="moveHandle"
2168+
/>
2169+
<div
2170+
className="rowContents"
2171+
>
2172+
<div
2173+
className="rowLabel"
2174+
>
2175+
<span
2176+
className="rowTitle"
2177+
>
2178+
B
2179+
</span>
2180+
</div>
2181+
<div
2182+
className="rowToolbar"
2183+
/>
2184+
</div>
2185+
</div>
2186+
</div>
2187+
</div>
2188+
</div>
2189+
</div>
2190+
<div
2191+
className="node"
2192+
style={
2193+
Object {
2194+
"height": 62,
2195+
"left": 0,
2196+
"position": "absolute",
2197+
"top": 124,
2198+
"width": "100%",
2199+
}
2200+
}
2201+
>
2202+
<div
2203+
className="lineBlock lineHalfVerticalTop lineHalfHorizontalRight"
2204+
style={
2205+
Object {
2206+
"width": 44,
2207+
}
2208+
}
2209+
/>
2210+
<div
2211+
className="nodeContent"
2212+
style={
2213+
Object {
2214+
"left": 44,
2215+
}
2216+
}
2217+
>
2218+
<div
2219+
style={
2220+
Object {
2221+
"height": "100%",
2222+
}
2223+
}
2224+
>
2225+
<div
2226+
className="rowWrapper"
2227+
>
2228+
<div
2229+
className="row"
2230+
style={
2231+
Object {
2232+
"opacity": 1,
2233+
}
2234+
}
2235+
>
2236+
<div
2237+
className="moveHandle"
2238+
/>
2239+
<div
2240+
className="rowContents"
2241+
>
2242+
<div
2243+
className="rowLabel"
2244+
>
2245+
<span
2246+
className="rowTitle"
2247+
>
2248+
C
2249+
</span>
2250+
</div>
2251+
<div
2252+
className="rowToolbar"
2253+
/>
2254+
</div>
2255+
</div>
2256+
</div>
2257+
</div>
2258+
</div>
2259+
</div>
2260+
</div>
2261+
</div>
2262+
</div>
2263+
</div>
2264+
</div>
2265+
</div>
2266+
<br />
2267+
<a
2268+
className="sourceLink"
2269+
href="https://github.com/fritz-c/react-sortable-tree/blob/master/examples/storybooks/callbacks.js"
2270+
rel="noopener noreferrer"
2271+
target="_top"
2272+
>
2273+
VIEW SOURCE →
2274+
</a>
2275+
</div>
2276+
`;
2277+
19642278
exports[`Storyshots Basics Minimal implementation 1`] = `
19652279
<div>
19662280
<div

examples/storybooks/callbacks.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { Component } from 'react';
2+
import SortableTree from '../../src';
3+
4+
export default class App extends Component {
5+
constructor(props) {
6+
super(props);
7+
8+
this.state = {
9+
treeData: [
10+
{ title: 'A', expanded: true, children: [{ title: 'B' }] },
11+
{ title: 'C' },
12+
],
13+
lastMovePrevPath: null,
14+
lastMoveNextPath: null,
15+
lastMoveNode: null,
16+
};
17+
}
18+
19+
render() {
20+
const { lastMovePrevPath, lastMoveNextPath, lastMoveNode } = this.state;
21+
22+
const recordCall = (name, args) => {
23+
// eslint-disable-next-line no-console
24+
console.log(`${name} called with arguments:`, args);
25+
};
26+
27+
return (
28+
<div>
29+
Open your console to see callback parameter info
30+
<div style={{ height: 300 }}>
31+
<SortableTree
32+
treeData={this.state.treeData}
33+
onChange={treeData => this.setState({ treeData })}
34+
// Need to set getNodeKey to get meaningful ids in paths
35+
getNodeKey={({ node }) => `node${node.title}`}
36+
onVisibilityToggle={args => recordCall('onVisibilityToggle', args)}
37+
onMoveNode={args => {
38+
recordCall('onMoveNode', args);
39+
const { prevPath, nextPath, node } = args;
40+
this.setState({
41+
lastMovePrevPath: prevPath,
42+
lastMoveNextPath: nextPath,
43+
lastMoveNode: node,
44+
});
45+
}}
46+
onDragStateChanged={args => recordCall('onDragStateChanged', args)}
47+
/>
48+
</div>
49+
{lastMoveNode && (
50+
<div>
51+
Node &quot;{lastMoveNode.title}&quot; moved from path [{lastMovePrevPath.join(
52+
','
53+
)}] to path [{lastMoveNextPath.join(',')}].
54+
</div>
55+
)}
56+
</div>
57+
);
58+
}
59+
}

0 commit comments

Comments
 (0)