Skip to content

feat: update react-dnd #531

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Merged
merged 8 commits into from
Oct 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
"start": "parcel website/index.html",
"prebuild": "npm run lint && npm run clean",
"build": "rollup -c",
"buildOnly": "rollup -c",
"build:storybook": "npm run clean:storybook && build-storybook -o build/storybook",
"build:website": "npm run clean:website && parcel build website/index.html -d build --public-url /react-sortable-tree/",
"clean": "rimraf dist",
"clean:storybook": "rimraf build/storybook",
"clean:website": "rimraf build",
"lint": "eslint src",
"prettier": "prettier --write \"{src,example/src,stories}/**/*.{js,css,md}\"",
"prepublishOnly": "npm run lint && npm run test && npm run build",
"prepublishOnly": "npm run test && npm run build",
"release": "standard-version",
"test": "jest",
"test:watch": "jest --watchAll",
Expand Down Expand Up @@ -51,7 +52,13 @@
"node_modules"
],
"moduleNameMapper": {
"\\.(css|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js"
"\\.(css|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"^dnd-core$": "dnd-core/dist/cjs",
"^react-dnd$": "react-dnd/dist/cjs",
"^react-dnd-html5-backend$": "react-dnd-html5-backend/dist/cjs",
"^react-dnd-touch-backend$": "react-dnd-touch-backend/dist/cjs",
"^react-dnd-test-backend$": "react-dnd-test-backend/dist/cjs",
"^react-dnd-test-utils$": "react-dnd-test-utils/dist/cjs"
}
},
"browserslist": [
Expand All @@ -63,8 +70,8 @@
"frontend-collective-react-dnd-scrollzone": "^1.0.2",
"lodash.isequal": "^4.5.0",
"prop-types": "^15.6.1",
"react-dnd": "^7.3.0",
"react-dnd-html5-backend": "^7.0.1",
"react-dnd": "^9.3.4",
"react-dnd-html5-backend": "^9.3.4",
"react-lifecycles-compat": "^3.0.4",
"react-sortable-tree": "^2.6.0",
"react-virtualized": "^9.19.1"
Expand All @@ -91,8 +98,8 @@
"codesandbox": "^1.2.10",
"coveralls": "^3.0.1",
"cross-env": "^5.1.6",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^5.9.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^3.3.0",
Expand All @@ -101,13 +108,13 @@
"eslint-plugin-react": "^7.8.2",
"gh-pages": "^2.0.1",
"jest": "^23.1.0",
"jest-enzyme": "^7.0.1",
"jest-enzyme": "^7.1.1",
"parcel-bundler": "^1.11.0",
"prettier": "^1.13.3",
"react": "^16.3.0",
"react-addons-shallow-compare": "^15.6.2",
"react-dnd-test-backend": "^7.0.1",
"react-dnd-touch-backend": "^0.6.0",
"react-dnd-test-backend": "^9.3.4",
"react-dnd-touch-backend": "^9.3.4",
"react-dom": "^16.3.0",
"react-hot-loader": "^4.3.0",
"react-sortable-tree-theme-file-explorer": "^1.1.2",
Expand Down
15 changes: 11 additions & 4 deletions src/react-sortable-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import withScrolling, {
createVerticalStrength,
createHorizontalStrength,
} from 'frontend-collective-react-dnd-scrollzone';
import { DragDropContextConsumer } from 'react-dnd';
import { DndProvider, DndContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { polyfill } from 'react-lifecycles-compat';
import 'react-virtualized/styles.css';
import TreeNode from './tree-node';
Expand Down Expand Up @@ -936,18 +937,24 @@ ReactSortableTree.defaultProps = {
polyfill(ReactSortableTree);

const SortableTreeWithoutDndContext = props => (
<DragDropContextConsumer>
<DndContext.Consumer>
{({ dragDropManager }) =>
dragDropManager === undefined ? null : (
<ReactSortableTree {...props} dragDropManager={dragDropManager} />
)
}
</DragDropContextConsumer>
</DndContext.Consumer>
);

const SortableTree = props => (
<DndProvider backend={HTML5Backend}>
<SortableTreeWithoutDndContext {...props}/>
</DndProvider>
)

// Export the tree component without the react-dnd DragDropContext,
// for when component is used with other components using react-dnd.
// see: https://github.com/gaearon/react-dnd/issues/186
export { SortableTreeWithoutDndContext };

export default DndManager.wrapRoot(SortableTreeWithoutDndContext);
export default SortableTree;
57 changes: 34 additions & 23 deletions src/react-sortable-tree.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
/* eslint-disable react/no-multi-comp */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import renderer from 'react-test-renderer';
import { mount } from 'enzyme';
import { List } from 'react-virtualized';
import { DragDropContext } from 'react-dnd';
import { DndProvider, DndContext } from 'react-dnd';
import TestBackend from 'react-dnd-test-backend';
import HTML5Backend from 'react-dnd-html5-backend';
import TouchBackend from 'react-dnd-touch-backend';
import SortableTree, {
Expand Down Expand Up @@ -401,41 +403,50 @@ describe('<SortableTree />', () => {
});

it('loads using SortableTreeWithoutDndContext', () => {
const HTML5Wrapped = DragDropContext(HTML5Backend)(
SortableTreeWithoutDndContext
);
const TouchWrapped = DragDropContext(TouchBackend)(
SortableTreeWithoutDndContext
);

expect(
mount(<HTML5Wrapped treeData={[{ title: 'a' }]} onChange={() => {}} />)
mount(
<DndProvider backend={HTML5Backend}>
<SortableTreeWithoutDndContext
treeData={[{ title: 'a' }]}
onChange={() => {}}
/>
</DndProvider>
)
).toBeDefined();
expect(
mount(<TouchWrapped treeData={[{ title: 'a' }]} onChange={() => {}} />)
mount(
<DndProvider backend={TouchBackend}>
<SortableTreeWithoutDndContext
treeData={[{ title: 'a' }]}
onChange={() => {}}
/>
</DndProvider>
)
).toBeDefined();
});

it('loads using SortableTreeWithoutDndContext', () => {
const TestWrapped = DragDropContext(HTML5Backend)(
SortableTreeWithoutDndContext
);

const onDragStateChanged = jest.fn();
const treeData = [{ title: 'a' }, { title: 'b' }];
let manager = null;

const wrapper = mount(
<TestWrapped
treeData={treeData}
onDragStateChanged={onDragStateChanged}
onChange={() => {}}
/>
<DndProvider backend={TestBackend}>
<DndContext.Consumer>
{({ dragDropManager }) => {
manager = dragDropManager;
}}
</DndContext.Consumer>
<SortableTreeWithoutDndContext
treeData={treeData}
onDragStateChanged={onDragStateChanged}
onChange={() => {}}
/>
</DndProvider>
);

// Obtain a reference to the backend
const backend = wrapper
.instance()
.getManager()
.getBackend();
const backend = manager.getBackend();

// Retrieve our DnD-wrapped node component type
const wrappedNodeType = wrapper.find('ReactSortableTree').instance()
Expand Down
11 changes: 1 addition & 10 deletions src/utils/dnd-manager.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
DragDropContext as dragDropContext,
DragSource as dragSource,
DropTarget as dropTarget,
} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { DragSource as dragSource, DropTarget as dropTarget } from 'react-dnd';
import { findDOMNode } from 'react-dom';
import { getDepth } from './tree-data-utils';
import { memoizedInsertNode } from './memoized-tree-data-utils';
Expand All @@ -13,10 +8,6 @@ export default class DndManager {
this.treeRef = treeRef;
}

static wrapRoot(el) {
return dragDropContext(HTML5Backend)(el);
}

get startDrag() {
return this.treeRef.startDrag;
}
Expand Down
29 changes: 15 additions & 14 deletions stories/drag-out-to-remove.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/no-multi-comp */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragDropContext, DropTarget } from 'react-dnd';
import { DndProvider, DropTarget } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { SortableTreeWithoutDndContext as SortableTree } from '../src';
// In your own app, you would need to use import styles once in the app
Expand Down Expand Up @@ -54,7 +54,7 @@ const TrashAreaComponent = DropTarget(
trashAreaCollect
)(trashAreaBaseComponent);

class UnwrappedApp extends Component {
class App extends Component {
constructor(props) {
super(props);

Expand All @@ -70,20 +70,21 @@ class UnwrappedApp extends Component {

render() {
return (
<div>
<TrashAreaComponent>
<div style={{ height: 250 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
dndType={trashAreaType}
/>
</div>
</TrashAreaComponent>
</div>
<DndProvider backend={HTML5Backend}>
<div>
<TrashAreaComponent>
<div style={{ height: 250 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
dndType={trashAreaType}
/>
</div>
</TrashAreaComponent>
</div>
</DndProvider>
);
}
}

const App = DragDropContext(HTML5Backend)(UnwrappedApp);
export default App;
26 changes: 14 additions & 12 deletions stories/external-node.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/no-multi-comp */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragDropContext, DragSource } from 'react-dnd';
import { DndProvider, DragSource } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { SortableTreeWithoutDndContext as SortableTree } from '../src';
// In your own app, you would need to use import styles once in the app
Expand Down Expand Up @@ -55,7 +55,7 @@ const YourExternalNodeComponent = DragSource(
externalNodeCollect
)(externalNodeBaseComponent);

class UnwrappedApp extends Component {
class App extends Component {
constructor(props) {
super(props);

Expand All @@ -66,19 +66,21 @@ class UnwrappedApp extends Component {

render() {
return (
<div>
<div style={{ height: 300 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
dndType={externalNodeType}
/>
<DndProvider backend={HTML5Backend}>
<div>
<div style={{ height: 300 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
dndType={externalNodeType}
/>
</div>
<YourExternalNodeComponent node={{ title: 'Baby Rabbit' }} />← drag
this
</div>
<YourExternalNodeComponent node={{ title: 'Baby Rabbit' }} />← drag this
</div>
</DndProvider>
);
}
}

const App = DragDropContext(HTML5Backend)(UnwrappedApp);
export default App;
30 changes: 15 additions & 15 deletions stories/touch-support.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable import/no-extraneous-dependencies */
import React, { Component } from 'react';
import { DragDropContext } from 'react-dnd';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import TouchBackend from 'react-dnd-touch-backend';
import { SortableTreeWithoutDndContext as SortableTree } from '../src';
Expand All @@ -9,8 +9,9 @@ import { SortableTreeWithoutDndContext as SortableTree } from '../src';

// https://stackoverflow.com/a/4819886/1601953
const isTouchDevice = !!('ontouchstart' in window || navigator.maxTouchPoints);
const dndBackend = isTouchDevice ? TouchBackend : HTML5Backend;

class UnwrappedApp extends Component {
class App extends Component {
constructor(props) {
super(props);

Expand All @@ -23,23 +24,22 @@ class UnwrappedApp extends Component {

render() {
return (
<div>
<span>
This is {!isTouchDevice && 'not '}a touch-supporting browser
</span>
<DndProvider backend={dndBackend}>
<div>
<span>
This is {!isTouchDevice && 'not '}a touch-supporting browser
</span>

<div style={{ height: 300 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
/>
<div style={{ height: 300 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
/>
</div>
</div>
</div>
</DndProvider>
);
}
}

const App = DragDropContext(isTouchDevice ? TouchBackend : HTML5Backend)(
UnwrappedApp
);
export default App;
Loading