react-dnd-multi-backend
Advanced tools
Comparing version 2.2.3 to 2.3.0
@@ -6,4 +6,3 @@ 'use strict'; | ||
}); | ||
exports.Preview = undefined; | ||
exports.default = createMultiBackend; | ||
exports.createTransition = exports.TouchTransition = exports.HTML5DragTransition = exports.Preview = undefined; | ||
@@ -18,7 +17,16 @@ var _MultiBackend = require('./MultiBackend'); | ||
var _Transitions = require('./Transitions'); | ||
var _createTransition = require('./createTransition'); | ||
var _createTransition2 = _interopRequireDefault(_createTransition); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var Preview = exports.Preview = _Preview2.default; | ||
exports.Preview = _Preview2.default; | ||
exports.HTML5DragTransition = _Transitions.HTML5DragTransition; | ||
exports.TouchTransition = _Transitions.TouchTransition; | ||
exports.createTransition = _createTransition2.default; | ||
function createMultiBackend(managerOrOptions) { | ||
exports.default = function (managerOrOptions) { | ||
if (managerOrOptions.getMonitor) { | ||
@@ -31,2 +39,2 @@ return new _MultiBackend2.default(managerOrOptions); | ||
} | ||
} | ||
}; |
@@ -6,38 +6,71 @@ 'use strict'; | ||
}); | ||
exports.default = undefined; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _HTML5toTouch = require('./HTML5toTouch'); | ||
var _reactDndHtml5Backend = require('react-dnd-html5-backend'); | ||
var _HTML5toTouch2 = _interopRequireDefault(_HTML5toTouch); | ||
var _reactDndHtml5Backend2 = _interopRequireDefault(_reactDndHtml5Backend); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _reactDndTouchBackend = require('react-dnd-touch-backend'); | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
var _reactDndTouchBackend2 = _interopRequireDefault(_reactDndTouchBackend); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _default = function _default(manager, sourceOptions) { | ||
var _this = this; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
_classCallCheck(this, _default); | ||
var Backend = { | ||
HTML5: 0, | ||
TOUCH: 1, | ||
MAX: 2 | ||
}; | ||
this.setup = function () { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
var MultiBackend = function () { | ||
function MultiBackend(manager, sourceOptions) { | ||
_classCallCheck(this, MultiBackend); | ||
if (_this.constructor.isSetUp) { | ||
throw new Error('Cannot have two MultiBackends at the same time.'); | ||
} | ||
_this.constructor.isSetUp = true; | ||
_this.addEventListeners(window); | ||
_this.backends[_this.current].instance.setup(); | ||
}; | ||
var options = Object.assign({ start: Backend.HTML5 }, sourceOptions || {}); | ||
this.teardown = function () { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
this.current = options.start; | ||
_this.constructor.isSetUp = false; | ||
_this.removeEventListeners(window); | ||
_this.backends[_this.current].instance.teardown(); | ||
}; | ||
this.backends = []; | ||
this.backends[Backend.HTML5] = new _reactDndHtml5Backend2.default(manager); | ||
this.backends[Backend.TOUCH] = new _reactDndTouchBackend2.default({ enableMouseEvents: true })(manager); | ||
this.connectDragSource = function () { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
this.nodes = {}; | ||
return _this.connectBackend('connectDragSource', args); | ||
}; | ||
var funcs = ['setup', 'teardown', 'connectDragSource', 'connectDragPreview', 'connectDropTarget', 'previewEnabled', 'addEventListeners', 'removeEventListeners', 'backendSwitcher', 'cleanUpHandlers', 'applyToBackend', 'callBackends', 'restrictTouchBackend', 'freeTouchBackend']; | ||
this.connectDragPreview = function () { | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
return _this.connectBackend('connectDragPreview', args); | ||
}; | ||
this.connectDropTarget = function () { | ||
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
return _this.connectBackend('connectDropTarget', args); | ||
}; | ||
this.previewEnabled = function () { | ||
return _this.backends[_this.current].preview; | ||
}; | ||
this.addEventListeners = function (target) { | ||
var _iteratorNormalCompletion = true; | ||
@@ -48,6 +81,8 @@ var _didIteratorError = false; | ||
try { | ||
for (var _iterator = funcs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var func = _step.value; | ||
for (var _iterator = _this.backends[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var backend = _step.value; | ||
this[func] = this[func].bind(this); | ||
if (backend.transition) { | ||
target.addEventListener(backend.transition.event, _this.backendSwitcher, true); | ||
} | ||
} | ||
@@ -68,212 +103,182 @@ } catch (err) { | ||
} | ||
} | ||
}; | ||
// DnD Backend API | ||
this.removeEventListeners = function (target) { | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = _this.backends[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var backend = _step2.value; | ||
_createClass(MultiBackend, [{ | ||
key: 'setup', | ||
value: function setup() { | ||
if (typeof window === 'undefined') { | ||
return; | ||
if (backend.transition) { | ||
target.removeEventListener(backend.transition.event, _this.backendSwitcher, true); | ||
} | ||
} | ||
if (this.constructor.isSetUp) { | ||
throw new Error('Cannot have two Multi backends at the same time.'); | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
this.constructor.isSetUp = true; | ||
this.addEventListeners(window); | ||
this.backends[this.current].setup(); | ||
} | ||
}, { | ||
key: 'teardown', | ||
value: function teardown() { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
}; | ||
this.constructor.isSetUp = false; | ||
this.removeEventListeners(window); | ||
this.backends[this.current].teardown(); | ||
} | ||
}, { | ||
key: 'connectDragSource', | ||
value: function connectDragSource() { | ||
return this.callBackends('connectDragSource', arguments); | ||
} | ||
}, { | ||
key: 'connectDragPreview', | ||
value: function connectDragPreview() { | ||
return this.callBackends('connectDragPreview', arguments); | ||
} | ||
}, { | ||
key: 'connectDropTarget', | ||
value: function connectDropTarget() { | ||
return this.callBackends('connectDropTarget', arguments); | ||
} | ||
this.backendSwitcher = function (event) { | ||
var oldBackend = _this.current; | ||
// Use by Preview component | ||
var i = 0; | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
}, { | ||
key: 'previewEnabled', | ||
value: function previewEnabled() { | ||
return this.current === Backend.TOUCH; | ||
} | ||
try { | ||
for (var _iterator3 = _this.backends[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var backend = _step3.value; | ||
// Multi Backend Listeners | ||
}, { | ||
key: 'addEventListeners', | ||
value: function addEventListeners(target) { | ||
target.addEventListener('touchstart', this.backendSwitcher, true); | ||
} | ||
}, { | ||
key: 'removeEventListeners', | ||
value: function removeEventListeners(target) { | ||
target.removeEventListener('touchstart', this.backendSwitcher, true); | ||
} | ||
// Switching logic | ||
}, { | ||
key: 'backendSwitcher', | ||
value: function backendSwitcher(event) { | ||
var oldBackend = this.current; | ||
if (this.current === Backend.HTML5 && event.touches != null) { | ||
this.current = Backend.TOUCH; | ||
this.removeEventListeners(window); | ||
if (i !== _this.current && backend.transition && backend.transition.check(event)) { | ||
_this.current = i; | ||
break; | ||
} | ||
i += 1; | ||
} | ||
if (this.current !== oldBackend) { | ||
this.backends[oldBackend].teardown(); | ||
this.cleanUpHandlers(oldBackend); | ||
this.backends[this.current].setup(); | ||
if (this.current === Backend.TOUCH) { | ||
this.freeTouchBackend(); | ||
this.backends[this.current].handleTopMoveStartCapture(event); | ||
this.backends[this.current].getTopMoveStartHandler()(event); | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3.return) { | ||
_iterator3.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
} | ||
}, { | ||
key: 'cleanUpHandlers', | ||
value: function cleanUpHandlers(backend) { | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
if (_this.current !== oldBackend) { | ||
_this.backends[oldBackend].instance.teardown(); | ||
var _iteratorNormalCompletion4 = true; | ||
var _didIteratorError4 = false; | ||
var _iteratorError4 = undefined; | ||
try { | ||
for (var _iterator2 = Object.keys(this.nodes)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var id = _step2.value; | ||
for (var _iterator4 = Object.keys(_this.nodes)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { | ||
var id = _step4.value; | ||
var node = this.nodes[id]; | ||
node.handlers[backend](); | ||
node.handlers[backend] = null; | ||
var node = _this.nodes[id]; | ||
node.handler(); | ||
node.handler = _this.callBackend(node.func, node.args); | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
_didIteratorError4 = true; | ||
_iteratorError4 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
if (!_iteratorNormalCompletion4 && _iterator4.return) { | ||
_iterator4.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
if (_didIteratorError4) { | ||
throw _iteratorError4; | ||
} | ||
} | ||
} | ||
} | ||
// Which backend should be called | ||
_this.backends[_this.current].instance.setup(); | ||
}, { | ||
key: 'applyToBackend', | ||
value: function applyToBackend(backend, func, args) { | ||
var self = this.backends[backend]; | ||
return self[func].apply(self, args); | ||
var newEvent = new event.constructor(event.type, event); | ||
event.target.dispatchEvent(newEvent); | ||
} | ||
}, { | ||
key: 'callBackends', | ||
value: function callBackends(func, args) { | ||
var handlers = []; | ||
var nodeId = func + '_' + args[0]; | ||
}; | ||
for (var i = 0; i < Backend.MAX; ++i) { | ||
if (i < this.current) { | ||
handlers.push(null); | ||
continue; | ||
} | ||
this.callBackend = function (func, args) { | ||
var _backends$current$ins; | ||
var touchAndNotCurrent = i == Backend.TOUCH && i != this.current; | ||
if (touchAndNotCurrent) { | ||
this.restrictTouchBackend(true); | ||
} | ||
handlers.push(this.applyToBackend(i, func, args)); | ||
if (touchAndNotCurrent) { | ||
this.restrictTouchBackend(false); | ||
} | ||
} | ||
return (_backends$current$ins = _this.backends[_this.current].instance)[func].apply(_backends$current$ins, _toConsumableArray(args)); | ||
}; | ||
var nodes = this.nodes; | ||
nodes[nodeId] = { func: func, args: args, handlers: handlers }; | ||
this.connectBackend = function (func, args) { | ||
var nodeId = func + '_' + args[0]; | ||
var handler = _this.callBackend(func, args); | ||
_this.nodes[nodeId] = { func: func, args: args, handler: handler }; | ||
return function () { | ||
delete nodes[nodeId]; | ||
for (var _i = 0; _i < handlers.length; ++_i) { | ||
var handler = handlers[_i]; | ||
if (handler) { | ||
handler(arguments); | ||
} | ||
} | ||
}; | ||
} | ||
return function () { | ||
var _nodes$nodeId; | ||
// Special cases for TouchBackend | ||
var r = (_nodes$nodeId = _this.nodes[nodeId]).handler.apply(_nodes$nodeId, arguments); | ||
delete _this.nodes[nodeId]; | ||
return r; | ||
}; | ||
}; | ||
}, { | ||
key: 'restrictTouchBackend', | ||
value: function restrictTouchBackend(enable) { | ||
this.backends[Backend.TOUCH].listenerTypes = enable ? ['touch'] : ['touch', 'mouse']; | ||
} | ||
}, { | ||
key: 'freeTouchBackend', | ||
value: function freeTouchBackend() { | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
var options = Object.assign({ backends: [] }, sourceOptions || {}); | ||
try { | ||
for (var _iterator3 = Object.keys(this.nodes)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var id = _step3.value; | ||
if (options.backends.length < 1) { | ||
options.backends = _HTML5toTouch2.default.backends; | ||
} | ||
var node = this.nodes[id]; | ||
node.handlers[Backend.TOUCH](); | ||
node.handlers[Backend.TOUCH] = this.applyToBackend(Backend.TOUCH, node.func, node.args); | ||
} | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3.return) { | ||
_iterator3.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
this.current = options.start || 0; | ||
this.backends = []; | ||
var _iteratorNormalCompletion5 = true; | ||
var _didIteratorError5 = false; | ||
var _iteratorError5 = undefined; | ||
try { | ||
for (var _iterator5 = options.backends[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { | ||
var backend = _step5.value; | ||
if (!backend.backend) { | ||
throw new Error('You must specify a \'backend\' property in your Backend entry: ' + backend); | ||
} | ||
var transition = backend.transition; | ||
if (transition && !transition._isMBTransition) { | ||
throw new Error('You must specify a valid \'transition\' property (either undefined or the return of \'createTransition\') in your Backend entry: ' + backend); | ||
} | ||
this.backends.push({ | ||
instance: new backend.backend(manager), | ||
preview: backend.preview || false, | ||
transition: transition | ||
}); | ||
} | ||
}]); | ||
} catch (err) { | ||
_didIteratorError5 = true; | ||
_iteratorError5 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion5 && _iterator5.return) { | ||
_iterator5.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError5) { | ||
throw _iteratorError5; | ||
} | ||
} | ||
} | ||
return MultiBackend; | ||
}(); | ||
this.nodes = {}; | ||
} | ||
MultiBackend.Backend = Backend; | ||
// DnD Backend API | ||
exports.default = MultiBackend; | ||
// Used by Preview component | ||
// Multi Backend Listeners | ||
// Switching logic | ||
; | ||
exports.default = _default; |
@@ -26,4 +26,4 @@ 'use strict'; | ||
}; | ||
}), _dec(_class = (_temp = _class2 = function (_Component) { | ||
_inherits(Preview, _Component); | ||
}), _dec(_class = (_temp = _class2 = function (_PureComponent) { | ||
_inherits(Preview, _PureComponent); | ||
@@ -53,6 +53,6 @@ function Preview() { | ||
return Preview; | ||
}(_react.Component), _class2.defaultProps = { currentOffset: { x: 0, y: 0 }, isDragging: false, itemType: '', item: '' }, _class2.propTypes = { | ||
}(_react.PureComponent), _class2.defaultProps = { currentOffset: { x: 0, y: 0 }, isDragging: false, itemType: '', item: {} }, _class2.propTypes = { | ||
currentOffset: _react.PropTypes.shape({ x: _react.PropTypes.number, y: _react.PropTypes.number }), | ||
isDragging: _react.PropTypes.bool, itemType: _react.PropTypes.string, item: _react.PropTypes.object, generator: _react.PropTypes.func.isRequired | ||
isDragging: _react.PropTypes.bool, itemType: _react.PropTypes.string, item: _react.PropTypes.any, generator: _react.PropTypes.func.isRequired | ||
}, _class2.contextTypes = { dragDropManager: _react.PropTypes.object }, _temp)) || _class); | ||
exports.default = Preview; |
{ | ||
"name": "react-dnd-multi-backend", | ||
"version": "2.2.3", | ||
"version": "2.3.0", | ||
"description": "Multi Backend system for React DnD", | ||
@@ -18,11 +18,14 @@ "author": "Louis Brunner <louis.brunner.fr@gmail.com> (https://github.com/LouisBrunner)", | ||
"scripts": { | ||
"clean": "rimraf lib", | ||
"build:lib": "babel src/lib --out-dir lib", | ||
"build:umd": "webpack", | ||
"build:examples": "webpack --config webpack/examples.js", | ||
"build": "npm run build:lib && npm run build:umd", | ||
"clean": "rm -rf lib", | ||
"build:lib": "babel src/lib --out-dir lib --ignore _spec.js", | ||
"build:dist": "webpack", | ||
"build:examples": "webpack --config webpack/examples.js && webpack --config webpack/examples_dist.js", | ||
"build": "npm run build:lib && npm run build:dist", | ||
"lint": "eslint .", | ||
"test": "echo 'No tests yet'", | ||
"test:watch": "npm run test -- --watch", | ||
"prepublish": "npm run lint && npm run clean && npm run test && npm run build" | ||
"test": "NODE_ENV=test NODE_PATH=$NODE_PATH:$PWD/src nyc mocha --opts ./.mocha.opts", | ||
"test:watch": "watch-run -i -p 'src/lib/**/*' npm run test", | ||
"travis-test": "NODE_ENV=test NODE_PATH=$NODE_PATH:$PWD/src nyc --reporter=lcov mocha --opts ./.mocha.opts", | ||
"travis-coverage": "cat ./coverage/lcov.info | coveralls", | ||
"start": "webpack-dev-server --config webpack/dev.js", | ||
"prepublishOnly": "npm run lint && npm run clean && npm run test && npm run build:lib" | ||
}, | ||
@@ -41,3 +44,3 @@ "repository": { | ||
"babel-loader": "^6.2.5", | ||
"babel-plugin-lodash": "^3.2.9", | ||
"babel-plugin-istanbul": "^4.0.0", | ||
"babel-plugin-transform-class-properties": "^6.16.0", | ||
@@ -47,16 +50,31 @@ "babel-plugin-transform-decorators-legacy": "^1.3.4", | ||
"babel-preset-react": "^6.16.0", | ||
"babel-register": "^6.24.0", | ||
"chai": "^3.5.0", | ||
"chai-enzyme": "^0.6.1", | ||
"coveralls": "^2.12.0", | ||
"enzyme": "^2.7.1", | ||
"eslint": "^3.8.1", | ||
"eslint-loader": "^1.6.1", | ||
"lodash-webpack-plugin": "^0.10.2", | ||
"react": "^0.14.0 || ^15.0.0-0", | ||
"react-dom": "^15.4.2", | ||
"rimraf": "^2.5.4", | ||
"webpack": "^1.13.2", | ||
"webpack-merge": "^2.4.0" | ||
"eslint-plugin-react": "^6.10.2", | ||
"jsdom": "^9.12.0", | ||
"jsdom-global": "^2.1.1", | ||
"mocha": "^3.2.0", | ||
"mocha-jsdom": "^1.1.0", | ||
"nyc": "^10.1.2", | ||
"react": "*", | ||
"react-addons-test-utils": "*", | ||
"react-dom": "*", | ||
"sinon": "^2.1.0", | ||
"sinon-chai": "^2.9.0", | ||
"sinon-spy-utils": "^1.0.0", | ||
"watch-run": "^1.2.5", | ||
"webpack": "^2.2.1", | ||
"webpack-dev-server": "^2.4.2", | ||
"webpack-merge": "^4.1.0" | ||
}, | ||
"dependencies": { | ||
"react-dnd": "^2.0.0", | ||
"react-dnd-html5-backend": "^2.0.0", | ||
"react-dnd-touch-backend": "^0.3.3" | ||
"react-dnd": "*", | ||
"react-dnd-html5-backend": "*", | ||
"react-dnd-touch-backend": "*" | ||
} | ||
} |
144
README.md
@@ -1,2 +0,2 @@ | ||
# React DnD Multi Backend [![NPM Version][npm-image]][npm-url] | ||
# React DnD Multi Backend [![NPM Version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![dependencies Status][deps-image]][deps-url] [![devDependencies Status][deps-dev-image]][deps-dev-url] | ||
@@ -6,31 +6,136 @@ [Try it here!](https://louisbrunner.github.io/react-dnd-multi-backend/examples) | ||
This project is a Drag'n'Drop backend compatible with [React DnD](https://github.com/gaearon/react-dnd). | ||
It enables your application to use different backends depending on the situation. The backend starts by using the [React DnD HTML5 Backend](https://github.com/gaearon/react-dnd-html5-backend), but switches to the [React DnD Touch Backend](https://github.com/yahoo/react-dnd-touch-backend) if a touch event is triggered. | ||
It enables your application to use different backends depending on the situation. | ||
You can either generate your own backend pipeline or use the default one (`HTML5toTouch`). | ||
[HTML5toTouch](src/lib/HTML5toTouch.js) starts by using the [React DnD HTML5 Backend](https://github.com/gaearon/react-dnd-html5-backend), but switches to the [React DnD Touch Backend](https://github.com/yahoo/react-dnd-touch-backend) if a touch event is triggered. | ||
You application can smoothly use the nice HTML5 compatible backend and fallback on the Touch one on mobile devices! | ||
Moreover, because the Touch backend doesn't support preview, a `Preview` component has been added to make it easier to mock the Drag'n'Drop "ghost". | ||
Moreover, because some backends don't support preview, a `Preview` component has been added to make it easier to mock the Drag'n'Drop "ghost". | ||
## Installation | ||
```bash | ||
npm install react-dnd-multi-backend | ||
### Node Installation | ||
```sh | ||
npm install react-dnd-multi-backend@next | ||
``` | ||
You can then use the minified UMD build in the `dist` folder. | ||
You can then `MultiBackend = require('react-dnd-multi-backend')` or `import MultiBackend from 'react-dnd-multi-backend'`. | ||
To get the `HTML5toTouch` pipeline, just require/import `react-dnd-multi-backend/lib/HTML5toTouch`. | ||
### Browser Installation | ||
Use the minified UMD build in the `dist` folder: [here](dist/ReactDnDMultiBackend.min.js). | ||
It exports a global `window.ReactDnDMultiBackend` when imported as a `<script>` tag. | ||
This file includes the `HTML5` and `Touch` backends, so no need to include them as well. | ||
If you want to use the `HTML5toTouch` pipeline, also include [RDMBHTML5toTouch.min.js](dist/RDMBHTML5toTouch.min.js). | ||
It exports a global `window.RDMBHTML5toTouch` when imported as a `<script>` tag. | ||
This file also includes the `HTML5` and `Touch` backends, so no need to include them as well. | ||
## Usage | ||
Every code snippet will be presented in 3 different styles: Node.js `require`, Node.js `import` and Browser Javascript (with required HTML `<script>`s). | ||
### Backend | ||
You can plug this backend in the `DragDropContext` the same way you do for any backend (e.g. `ReactDnDHTML5Backend`), you can see [the docs](http://gaearon.github.io/react-dnd/docs-html5-backend.html) for more information. | ||
You can also pass options to change the Backend behavior. Supported options are: | ||
You must pass a 'pipeline' to use as argument. This package includes `HTML5toTouch`, but you can write your own. | ||
- `start`: change the starting backend with `ReactDnDMultiBackend.Backend.HTML5` or `ReactDnDMultiBackend.Backend.Touch` | ||
- *require*: | ||
```js | ||
var ReactDnD = require('react-dnd'); | ||
var MultiBackend = require('react-dnd-multi-backend').default; | ||
var HTML5toTouch = require('react-dnd-multi-backend/lib/HTML5toTouch').default; // or any other pipeline | ||
... | ||
module.exports = ReactDnD.DragDropContext(MultiBackend(HTML5toTouch))(App); | ||
``` | ||
- *import*: | ||
```js | ||
import { DragDropContext } from 'react-dnd'; | ||
import MultiBackend from 'react-dnd-multi-backend'; | ||
import HTML5toTouch from 'react-dnd-multi-backend/lib/HTML5toTouch'; // or any other pipeline | ||
... | ||
export default DragDropContext(MultiBackend(HTML5toTouch))(App); | ||
``` | ||
- *browser*: | ||
```js | ||
<script src="ReactDnDMultiBackend.min.js"></script> | ||
<script src="RDMBHTML5toTouch.min.js"></script> <!-- or any other pipeline --> | ||
... | ||
var AppDnD = ReactDnD.DragDropContext(ReactDnDMultiBackend.default(RDMBHTML5toTouch.default))(App); // `.default` is only used to get the ES6 module default export | ||
``` | ||
### Create a custom pipeline | ||
Creating a pipeline is fairly easy. A pipeline is composed of a list of backends, the first one will be the default one, loaded at the start of the **MultiBackend**, the order of the rest isn't important. | ||
Each backend entry must specify one property: `backend`, containing the class of the Backend to instantiate. | ||
But other options are available: `preview` (a boolean indicating if `Preview` components should be shown) and `transition` (an object returned by the `createTransition` function). | ||
Here is the `HTML5toTouch` pipeline code as an example: | ||
```js | ||
... | ||
import HTML5Backend from 'react-dnd-html5-backend'; | ||
import TouchBackend from 'react-dnd-touch-backend'; | ||
import MultiBackend, { TouchTransition } from 'react-dnd-multi-backend'; | ||
... | ||
const HTML5toTouch = { | ||
backends: [ | ||
{ | ||
backend: HTML5Backend | ||
}, | ||
{ | ||
backend: TouchBackend({enableMouseEvents: true}), // Note that you can call your backends with options | ||
preview: true, | ||
transition: TouchTransition | ||
} | ||
] | ||
}; | ||
... | ||
export default DragDropContext(MultiBackend(HTML5toTouch))(App); | ||
``` | ||
`TouchTransition` is a predefined transition that you can use in your own pipelines, it is triggered when a *touchstart* is received. Transitions rea really easy to write, here is an example: | ||
```js | ||
import { createTransition } from 'react-dnd-multi-backend'; | ||
const TouchTransition = createTransition('touchstart', (event) => { | ||
return event.touches != null; | ||
}); | ||
``` | ||
You can also import `HTML5DragTransition` which works the same way, but detects when a HTML5 DragEvent is received. | ||
### Preview | ||
Concerning the `Preview` class, it is created using the following snippet: | ||
``` | ||
var MultiBackend = require('react-dnd-multi-backend'); | ||
- *require*: | ||
```js | ||
var MultiBackend = require('react-dnd-multi-backend').default; | ||
... | ||
<MultiBackend.Preview generator={this.generatePreview} /> | ||
``` | ||
- *import*: | ||
```js | ||
import MultiBackend, { Preview } from 'react-dnd-multi-backend'; | ||
... | ||
<Preview generator={this.generatePreview} /> | ||
``` | ||
- *browser*: | ||
```js | ||
<script src="ReactDnDMultiBackend.min.js"></script> | ||
... | ||
<ReactDnDMultiBackend.Preview generator={this.generatePreview} /> | ||
``` | ||
You must pass a function as the `generator` prop which takes 3 arguments: | ||
@@ -42,6 +147,10 @@ | ||
Note that this component will only be showed while using the Touch backend. | ||
Note that this component will only be showed while using a backend flagged with `preview: true` (see [Create a custom pipeline](#create-a-custom-pipeline)) which is the case for the Touch backend in the default `HTML5toTouch` pipeline. | ||
You can see an example [here](https://github.com/LouisBrunner/react-dnd-multi-backend/blob/master/src/examples/). | ||
### Example | ||
You can see an example [here](src/examples/) (Node.js style with `import`s). | ||
## Thanks | ||
@@ -51,2 +160,3 @@ | ||
## License | ||
@@ -60,1 +170,9 @@ | ||
[npm-url]: https://npmjs.org/package/react-dnd-multi-backend | ||
[travis-image]: https://travis-ci.org/LouisBrunner/react-dnd-multi-backend.svg?branch=master | ||
[travis-url]: https://travis-ci.org/LouisBrunner/react-dnd-multi-backend | ||
[coveralls-image]: https://coveralls.io/repos/github/LouisBrunner/react-dnd-multi-backend/badge.svg?branch=master | ||
[coveralls-url]: https://coveralls.io/github/LouisBrunner/react-dnd-multi-backend?branch=master | ||
[deps-image]: https://david-dm.org/louisbrunner/react-dnd-multi-backend/status.svg | ||
[deps-url]: https://david-dm.org/louisbrunner/react-dnd-multi-backend | ||
[deps-dev-image]: https://david-dm.org/louisbrunner/react-dnd-multi-backend/dev-status.svg | ||
[deps-dev-url]: https://david-dm.org/louisbrunner/react-dnd-multi-backend?type=dev |
Sorry, the diff of this file is not supported yet
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 3 instances in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
0
175
25520
31
10
339
3
+ Added@babel/runtime@7.26.9(transitive)
+ Added@react-dnd/asap@5.0.2(transitive)
+ Added@react-dnd/invariant@4.0.2(transitive)
+ Added@react-dnd/shallowequal@4.0.2(transitive)
+ Addeddnd-core@16.0.1(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedhoist-non-react-statics@3.3.2(transitive)
+ Addedreact-dnd@16.0.1(transitive)
+ Addedreact-dnd-html5-backend@16.0.1(transitive)
+ Addedreact-dnd-touch-backend@16.0.1(transitive)
+ Addedredux@4.2.1(transitive)
+ Addedregenerator-runtime@0.14.1(transitive)
- Removedasap@2.0.6(transitive)
- Removeddisposables@1.0.2(transitive)
- Removeddnd-core@2.6.0(transitive)
- Removedhoist-non-react-statics@2.5.5(transitive)
- Removedinvariant@2.2.4(transitive)
- Removedjs-tokens@4.0.0(transitive)
- Removedlodash@4.17.21(transitive)
- Removedlodash-es@4.17.21(transitive)
- Removedloose-envify@1.4.0(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact-dnd@2.6.0(transitive)
- Removedreact-dnd-html5-backend@2.6.0(transitive)
- Removedreact-dnd-touch-backend@0.3.21(transitive)
- Removedredux@3.7.2(transitive)
- Removedsymbol-observable@1.2.0(transitive)
Updatedreact-dnd@*
Updatedreact-dnd-html5-backend@*
Updatedreact-dnd-touch-backend@*