diff --git a/.babelrc b/.babelrc deleted file mode 100644 index e0fe8ac..0000000 --- a/.babelrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - "es2015", - "stage-1", - "react" - ] -} diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000..f6058c8 --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,9 @@ +module.exports = { + presets: [ + '@babel/preset-env', + '@babel/preset-react', + ], + plugins: [ + '@babel/plugin-proposal-class-properties', + ], +} diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 735c117..0000000 --- a/.eslintrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parser": "babel-eslint", - "extends": "airbnb", - - "ecmaFeatures": { - "modules": true - }, - - "rules": { - "no-unused-vars": [0], - "react/prop-types": [0] - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..fc6a278 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + parser: 'babel-eslint', + extends: 'airbnb', + + rules: { + 'react/jsx-filename-extension': 0, + 'no-unused-vars': 0, + 'react/prop-types': 0, + }, + + env: { + browser: true, + mocha: true + }, +} diff --git a/package.json b/package.json index bc79bb9..55573c7 100644 --- a/package.json +++ b/package.json @@ -38,30 +38,35 @@ }, "license": "MIT", "dependencies": { - "hoist-non-react-statics": "^1.2.0", + "hoist-non-react-statics": "^3.1.0", "lodash.throttle": "^4.0.1", "prop-types": "^15.5.9", "raf": "^3.2.0", - "react-display-name": "^0.2.0" + "react": "^16.3.0", + "react-display-name": "^0.2.0", + "react-dom": "^16.3.0" }, "devDependencies": { - "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", - "chai": "^3.4.1", - "eslint": "^2.12.0", - "eslint-config-airbnb": "^9.0.1", - "eslint-plugin-import": "^1.8.1", - "eslint-plugin-jsx-a11y": "^1.4.2", - "eslint-plugin-react": "^5.1.1", + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@babel/register": "^7.0.0", + "babel-eslint": "^10.0.1", + "chai": "^4.2.0", + "eslint": "^5.9.0", + "eslint-config-airbnb": "^17.1.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-jsx-a11y": "^6.1.2", + "eslint-plugin-react": "^7.11.1", "in-publish": "^2.0.0", - "mocha": "^2.3.4", - "react": "^15.1.0", - "react-dom": "^15.1.0", - "sinon": "^1.17.2", - "sinon-chai": "^2.8.0" + "mocha": "^5.2.0", + "react-dnd": "^7.0.2", + "sinon": "^7.1.1", + "sinon-chai": "^3.2.0" + }, + "peerDependencies": { + "react-dnd": "^6.0.0 || ^7.0.0" } } diff --git a/src/index.js b/src/index.js index dcffbd3..e779abb 100644 --- a/src/index.js +++ b/src/index.js @@ -4,13 +4,16 @@ import { findDOMNode } from 'react-dom'; import throttle from 'lodash.throttle'; import raf from 'raf'; import getDisplayName from 'react-display-name'; +import { Consumer as DragDropContextConsumer } from 'react-dnd/lib/DragDropContext'; import hoist from 'hoist-non-react-statics'; import { noop, intBetween, getCoords } from './util'; const DEFAULT_BUFFER = 150; export function createHorizontalStrength(_buffer) { - return function defaultHorizontalStrength({ x, w, y, h }, point) { + return function defaultHorizontalStrength({ + x, w, y, h, + }, point) { const buffer = Math.min(w / 2, _buffer); const inRange = point.x >= x && point.x <= x + w; const inBox = inRange && point.y >= y && point.y <= y + h; @@ -18,7 +21,8 @@ export function createHorizontalStrength(_buffer) { if (inBox) { if (point.x < x + buffer) { return (point.x - x - buffer) / buffer; - } else if (point.x > (x + w - buffer)) { + } + if (point.x > (x + w - buffer)) { return -(x + w - point.x - buffer) / buffer; } } @@ -28,7 +32,9 @@ export function createHorizontalStrength(_buffer) { } export function createVerticalStrength(_buffer) { - return function defaultVerticalStrength({ y, h, x, w }, point) { + return function defaultVerticalStrength({ + y, h, x, w, + }, point) { const buffer = Math.min(h / 2, _buffer); const inRange = point.y >= y && point.y <= y + h; const inBox = inRange && point.x >= x && point.x <= x + w; @@ -36,7 +42,8 @@ export function createVerticalStrength(_buffer) { if (inBox) { if (point.y < y + buffer) { return (point.y - y - buffer) / buffer; - } else if (point.y > (y + h - buffer)) { + } + if (point.y > (y + h - buffer)) { return -(y + h - point.y - buffer) / buffer; } } @@ -50,12 +57,13 @@ export const defaultHorizontalStrength = createHorizontalStrength(DEFAULT_BUFFER export const defaultVerticalStrength = createVerticalStrength(DEFAULT_BUFFER); -export default function createScrollingComponent(WrappedComponent) { +export function createScrollingComponent(WrappedComponent) { class ScrollingComponent extends Component { - static displayName = `Scrolling(${getDisplayName(WrappedComponent)})`; static propTypes = { + // eslint-disable-next-line react/forbid-prop-types + dragDropManager: PropTypes.object.isRequired, onScrollChange: PropTypes.func, verticalStrength: PropTypes.func, horizontalStrength: PropTypes.func, @@ -69,13 +77,33 @@ export default function createScrollingComponent(WrappedComponent) { strengthMultiplier: 30, }; - static contextTypes = { - dragDropManager: PropTypes.object, - }; + // 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 coords = getCoords(evt); + + // calculate strength + const { horizontalStrength, verticalStrength } = this.props; + this.scaleX = horizontalStrength(box, coords); + this.scaleY = verticalStrength(box, coords); + + // start scrolling if we need to + if (!this.frame && (this.scaleX || this.scaleY)) { + this.startScrolling(); + } + }, 100, { trailing: false }) constructor(props, ctx) { super(props, ctx); + this.wrappedInstance = React.createRef(); + this.scaleX = 0; this.scaleY = 0; this.frame = null; @@ -85,16 +113,17 @@ export default function createScrollingComponent(WrappedComponent) { } componentDidMount() { - this.container = findDOMNode(this.wrappedInstance); + // eslint-disable-next-line react/no-find-dom-node + this.container = findDOMNode(this.wrappedInstance.current); 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 window.document.body.addEventListener('touchmove', this.handleEvent); - this.clearMonitorSubscription = this.context - .dragDropManager - .getMonitor() - .subscribeToStateChange(() => this.handleMonitorChange()); + const { dragDropManager } = this.props; + this.clearMonitorSubscription = dragDropManager + .getMonitor() + .subscribeToStateChange(() => this.handleMonitorChange()); } componentWillUnmount() { @@ -112,7 +141,8 @@ export default function createScrollingComponent(WrappedComponent) { } handleMonitorChange() { - const isDragging = this.context.dragDropManager.getMonitor().isDragging(); + const { dragDropManager } = this.props; + const isDragging = dragDropManager.getMonitor().isDragging(); if (!this.dragging && isDragging) { this.dragging = true; @@ -134,23 +164,6 @@ export default function createScrollingComponent(WrappedComponent) { window.document.body.removeEventListener('touchmove', this.updateScrolling); } - // 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 coords = getCoords(evt); - - // calculate strength - this.scaleX = this.props.horizontalStrength(box, coords); - this.scaleY = this.props.verticalStrength(box, coords); - - // start scrolling if we need to - if (!this.frame && (this.scaleX || this.scaleY)) { - this.startScrolling(); - } - }, 100, { trailing: false }) - startScrolling() { let i = 0; const tick = () => { @@ -167,7 +180,8 @@ export default function createScrollingComponent(WrappedComponent) { // mousemove events from a container that also emits a scroll // event that same frame. So we double the strengthMultiplier and only adjust // the scroll position at 30fps - if (i++ % 2) { + i += 1; + if (i % 2) { const { scrollLeft, scrollTop, @@ -181,7 +195,7 @@ export default function createScrollingComponent(WrappedComponent) { ? container.scrollLeft = intBetween( 0, scrollWidth - clientWidth, - scrollLeft + scaleX * strengthMultiplier + scrollLeft + scaleX * strengthMultiplier, ) : scrollLeft; @@ -189,7 +203,7 @@ export default function createScrollingComponent(WrappedComponent) { ? container.scrollTop = intBetween( 0, scrollHeight - clientHeight, - scrollTop + scaleY * strengthMultiplier + scrollTop + scaleY * strengthMultiplier, ) : scrollTop; @@ -220,12 +234,12 @@ export default function createScrollingComponent(WrappedComponent) { horizontalStrength, onScrollChange, - ...props, + ...props } = this.props; return ( { this.wrappedInstance = ref; }} + ref={this.wrappedInstance} {...props} /> ); @@ -234,3 +248,16 @@ export default function createScrollingComponent(WrappedComponent) { return hoist(ScrollingComponent, WrappedComponent); } + +export default function createScrollingComponentWithConsumer(WrappedComponent) { + const ScrollingComponent = createScrollingComponent(WrappedComponent); + return props => ( + + {({ dragDropManager }) => ( + dragDropManager === undefined + ? null + : + )} + + ); +} diff --git a/src/util.js b/src/util.js index 5d99f15..07245dd 100644 --- a/src/util.js +++ b/src/util.js @@ -5,7 +5,7 @@ export function noop() { export function intBetween(min, max, val) { return Math.floor( - Math.min(max, Math.max(min, val)) + Math.min(max, Math.max(min, val)), ); } diff --git a/test/mocha.opts b/test/mocha.opts index 606db34..40c9133 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,4 +1,4 @@ ---require babel-register +--require @babel/register --require test/setup --check-leaks --throw-deprecation