diff --git a/examples/scrollingElement/.gitignore b/examples/scrollingElement/.gitignore new file mode 100644 index 0000000..927d17b --- /dev/null +++ b/examples/scrollingElement/.gitignore @@ -0,0 +1,18 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +/node_modules + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env +npm-debug.log* +yarn-debug.log* +yarn-error.log* + diff --git a/examples/scrollingElement/README.md b/examples/scrollingElement/README.md new file mode 100644 index 0000000..d1975b0 --- /dev/null +++ b/examples/scrollingElement/README.md @@ -0,0 +1,7 @@ +# Basic Example + +```bash +# in this directory +npm install +npm start +``` diff --git a/examples/scrollingElement/package.json b/examples/scrollingElement/package.json new file mode 100644 index 0000000..38c05a7 --- /dev/null +++ b/examples/scrollingElement/package.json @@ -0,0 +1,28 @@ +{ + "name": "scrollingElement", + "version": "0.1.0", + "private": true, + "devDependencies": { + "react-scripts": "0.9.5", + "babel-cli": "^6.4.5", + "babel-eslint": "^6.0.4", + "babel-preset-es2015": "^6.3.13", + "babel-preset-react": "^6.5.0", + "babel-preset-stage-1": "^6.3.13", + "babel-register": "^6.4.3" + }, + "dependencies": { + "prop-types": "^15.5.9", + "react": "^15.5.4", + "react-dnd": "^2.4.0", + "react-dnd-html5-backend": "^2.4.1", + "react-dnd-scrollzone": "^3.1.0", + "react-dom": "^15.5.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + } +} diff --git a/examples/scrollingElement/public/favicon.ico b/examples/scrollingElement/public/favicon.ico new file mode 100644 index 0000000..5c125de Binary files /dev/null and b/examples/scrollingElement/public/favicon.ico differ diff --git a/examples/scrollingElement/public/index.html b/examples/scrollingElement/public/index.html new file mode 100644 index 0000000..aab5e3b --- /dev/null +++ b/examples/scrollingElement/public/index.html @@ -0,0 +1,31 @@ + + + + + + + + React App + + +
+ + + diff --git a/examples/scrollingElement/src/App.css b/examples/scrollingElement/src/App.css new file mode 100644 index 0000000..4c4fc7f --- /dev/null +++ b/examples/scrollingElement/src/App.css @@ -0,0 +1,3 @@ +.App { + border: solid 2px black; +} diff --git a/examples/scrollingElement/src/App.js b/examples/scrollingElement/src/App.js new file mode 100644 index 0000000..149e5bc --- /dev/null +++ b/examples/scrollingElement/src/App.js @@ -0,0 +1,24 @@ +import React, { Component } from 'react'; +import HTML5Backend from 'react-dnd-html5-backend'; +import { DragDropContextProvider } from 'react-dnd'; +import withScrolling from 'react-dnd-scrollzone'; +import DragItem from './DragItem'; +import './App.css'; + +const ScrollingComponent = withScrolling('div'); + +const ITEMS = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]; + +export default class App extends Component { + render() { + return ( + + + {ITEMS.map(n => ( + + ))} + + + ); + } +} diff --git a/examples/scrollingElement/src/DragItem.css b/examples/scrollingElement/src/DragItem.css new file mode 100644 index 0000000..fc7509c --- /dev/null +++ b/examples/scrollingElement/src/DragItem.css @@ -0,0 +1,5 @@ +.DragItem { + width: 100%; + border: solid 1px black; + padding: 30px; +} diff --git a/examples/scrollingElement/src/DragItem.js b/examples/scrollingElement/src/DragItem.js new file mode 100644 index 0000000..cd1b0f5 --- /dev/null +++ b/examples/scrollingElement/src/DragItem.js @@ -0,0 +1,31 @@ +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; +import { DragSource } from 'react-dnd'; +import './DragItem.css'; + +class DragItem extends PureComponent { + + static propTypes = { + label: PropTypes.string.isRequired, + }; + + render() { + return this.props.dragSource( +
+ {this.props.label} +
+ ); + } +} + +export default DragSource( + 'foo', + { + beginDrag() { + return {} + } + }, + (connect) => ({ + dragSource: connect.dragSource(), + }) +)(DragItem); diff --git a/examples/scrollingElement/src/index.css b/examples/scrollingElement/src/index.css new file mode 100644 index 0000000..b4cc725 --- /dev/null +++ b/examples/scrollingElement/src/index.css @@ -0,0 +1,5 @@ +body { + margin: 0; + padding: 0; + font-family: sans-serif; +} diff --git a/examples/scrollingElement/src/index.js b/examples/scrollingElement/src/index.js new file mode 100644 index 0000000..54c5ef1 --- /dev/null +++ b/examples/scrollingElement/src/index.js @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import './index.css'; + +ReactDOM.render( + , + document.getElementById('root') +); diff --git a/src/index.js b/src/index.js index dcffbd3..5e83b2d 100644 --- a/src/index.js +++ b/src/index.js @@ -60,6 +60,7 @@ export default function createScrollingComponent(WrappedComponent) { verticalStrength: PropTypes.func, horizontalStrength: PropTypes.func, strengthMultiplier: PropTypes.number, + scrollingElement: PropTypes.bool }; static defaultProps = { @@ -85,7 +86,7 @@ export default function createScrollingComponent(WrappedComponent) { } componentDidMount() { - this.container = findDOMNode(this.wrappedInstance); + this.container = this.props.scrollingElement ? document.scrollingElement : findDOMNode(this.wrappedInstance); this.container.addEventListener('dragover', this.handleEvent); // touchmove events don't seem to work across siblings, so we unfortunately // have to attach the listeners to the body @@ -109,7 +110,7 @@ export default function createScrollingComponent(WrappedComponent) { this.attach(); this.updateScrolling(evt); } - } + }; handleMonitorChange() { const isDragging = this.context.dragDropManager.getMonitor().isDragging(); @@ -134,11 +135,27 @@ export default function createScrollingComponent(WrappedComponent) { window.document.body.removeEventListener('touchmove', this.updateScrolling); } + viewportHeight() { + return Math.max(document.documentElement.clientHeight, window.innerHeight || 0) + } + + viewportWidth() { + return Math.max(document.documentElement.clientWidth, window.innerWidth || 0) + } + // Update scaleX and scaleY every 100ms or so // and start scrolling if necessary updateScrolling = throttle(evt => { const { left: x, top: y, width: w, height: h } = this.container.getBoundingClientRect(); - const box = { x, y, w, h }; + const box = this.props.scrollingElement ? + { + x: 0, + y: 0, + w: this.viewportWidth(), + h: this.viewportHeight() + } : + { x, y, w, h } + ; const coords = getCoords(evt); // calculate strength @@ -149,7 +166,7 @@ export default function createScrollingComponent(WrappedComponent) { if (!this.frame && (this.scaleX || this.scaleY)) { this.startScrolling(); } - }, 100, { trailing: false }) + }, 100, { trailing: false }); startScrolling() { let i = 0; @@ -168,7 +185,7 @@ export default function createScrollingComponent(WrappedComponent) { // event that same frame. So we double the strengthMultiplier and only adjust // the scroll position at 30fps if (i++ % 2) { - const { + let { scrollLeft, scrollTop, scrollWidth, @@ -176,6 +193,10 @@ export default function createScrollingComponent(WrappedComponent) { clientWidth, clientHeight, } = container; + if (this.props.scrollingElement) { + clientHeight = this.viewportHeight(); + clientWidth = this.viewportWidth(); + } const newLeft = scaleX ? container.scrollLeft = intBetween( @@ -219,6 +240,7 @@ export default function createScrollingComponent(WrappedComponent) { verticalStrength, horizontalStrength, onScrollChange, + scrollingElement, ...props, } = this.props;