react-sortable-hoc
Advanced tools
Comparing version 0.2.0 to 0.3.0
Changelog | ||
------------ | ||
### 0.3.0 | ||
Added grid support for elements of equal widths / heights [#4](https://github.com/clauderic/react-sortable-hoc/issues/4) [#86](https://github.com/clauderic/react-sortable-hoc/pull/86). Huge shout-out to [@richmeij](https://github.com/richmeij) for making this happen! | ||
@@ -4,0 +6,0 @@ ### 0.2.0 |
@@ -159,3 +159,6 @@ 'use strict'; | ||
_this.margin = margin; | ||
_this.dimension = axis === 'x' ? _this.width : _this.height; | ||
_this.width = node.offsetWidth; | ||
_this.height = node.offsetHeight; | ||
_this.halfWidth = _this.width / 2; | ||
_this.halfHeight = _this.height / 2; | ||
_this.marginOffset = { | ||
@@ -166,9 +169,16 @@ x: _this.margin.left + _this.margin.right, | ||
_this.boundingClientRect = node.getBoundingClientRect(); | ||
_this.containerBoundingRect = containerBoundingRect; | ||
_this.index = index; | ||
_this.newIndex = index; | ||
var edge = _this.edge = axis === 'x' ? 'Left' : 'Top'; | ||
_this.offsetEdge = _this.getEdgeOffset(edge, node); | ||
_this.axis = { | ||
x: axis.indexOf('x') >= 0, | ||
y: axis.indexOf('y') >= 0 | ||
}; | ||
_this.offsetEdge = _this.getEdgeOffset(node); | ||
_this.initialOffset = _this.getOffset(e); | ||
_this.initialScroll = _this.scrollContainer['scroll' + edge]; | ||
_this.initialScroll = { | ||
top: _this.scrollContainer.scrollTop, | ||
left: _this.scrollContainer.scrollLeft | ||
}; | ||
@@ -187,9 +197,12 @@ _this.helper = _this.document.body.appendChild(node.cloneNode(true)); | ||
if (axis === 'x') { | ||
_this.minTranslate = (useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - _this.boundingClientRect.left - _this.width / 2; | ||
_this.maxTranslate = (useWindowAsScrollContainer ? _this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - _this.boundingClientRect.left - _this.width / 2; | ||
} else { | ||
_this.minTranslate = (useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - _this.boundingClientRect.top - _this.height / 2; | ||
_this.maxTranslate = (useWindowAsScrollContainer ? _this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - _this.boundingClientRect.top - _this.height / 2; | ||
_this.minTranslate = {}; | ||
_this.maxTranslate = {}; | ||
if (_this.axis.x) { | ||
_this.minTranslate.x = (useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - _this.boundingClientRect.left - _this.halfWidth; | ||
_this.maxTranslate.x = (useWindowAsScrollContainer ? _this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - _this.boundingClientRect.left - _this.halfWidth; | ||
} | ||
if (_this.axis.y) { | ||
_this.minTranslate.y = (useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - _this.boundingClientRect.top - _this.halfHeight; | ||
_this.maxTranslate.y = (useWindowAsScrollContainer ? _this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - _this.boundingClientRect.top - _this.halfHeight; | ||
} | ||
@@ -293,16 +306,31 @@ if (helperClass) { | ||
var translate = _this.translate; | ||
var direction = 0; | ||
var speed = 1; | ||
var acceleration = 10; | ||
var direction = { | ||
x: 0, | ||
y: 0 | ||
}; | ||
var speed = { | ||
x: 1, | ||
y: 1 | ||
}; | ||
var acceleration = { | ||
x: 10, | ||
y: 10 | ||
}; | ||
if (translate >= _this.maxTranslate - _this.dimension / 2) { | ||
direction = 1; // Scroll Down | ||
speed = acceleration * Math.abs((_this.maxTranslate - _this.dimension / 2 - translate) / _this.dimension); | ||
} else if (translate <= _this.minTranslate + _this.dimension / 2) { | ||
direction = -1; // Scroll Up | ||
speed = acceleration * Math.abs((translate - _this.dimension / 2 - _this.minTranslate) / _this.dimension); | ||
if (translate.y >= _this.maxTranslate.y - _this.halfHeight) { | ||
direction.y = 1; // Scroll Down | ||
speed.y = acceleration.y * Math.abs((_this.maxTranslate.y - _this.halfHeight - translate.y) / _this.height); | ||
} else if (translate.x >= _this.maxTranslate.x - _this.halfWidth) { | ||
direction.x = 1; // Scroll Right | ||
speed.x = acceleration.x * Math.abs((_this.maxTranslate.x - _this.halfWidth - translate.x) / _this.width); | ||
} else if (translate.y <= _this.minTranslate.y + _this.halfHeight) { | ||
direction.y = -1; // Scroll Up | ||
speed.y = acceleration.y * Math.abs((translate.y - _this.halfHeight - _this.minTranslate.y) / _this.height); | ||
} else if (translate.x <= _this.minTranslate.x + _this.halfWidth) { | ||
direction.x = -1; // Scroll Left | ||
speed.x = acceleration.x * Math.abs((translate.x - _this.halfWidth - _this.minTranslate.x) / _this.width); | ||
} | ||
if (_this.autoscrollInterval) { | ||
clearTimeout(_this.autoscrollInterval); | ||
clearInterval(_this.autoscrollInterval); | ||
_this.autoscrollInterval = null; | ||
@@ -312,8 +340,13 @@ _this.isAutoScrolling = false; | ||
if (direction !== 0) { | ||
if (direction.x !== 0 || direction.y !== 0) { | ||
_this.autoscrollInterval = setInterval(function () { | ||
_this.isAutoScrolling = true; | ||
var offset = 1 * speed * direction; | ||
_this.scrollContainer['scroll' + _this.edge] += offset; | ||
_this.translate += offset; | ||
var offset = { | ||
left: 1 * speed.x * direction.x, | ||
top: 1 * speed.y * direction.y | ||
}; | ||
_this.scrollContainer.scrollTop += offset.top; | ||
_this.scrollContainer.scrollLeft += offset.left; | ||
_this.translate.x += offset.left; | ||
_this.translate.y += offset.top; | ||
_this.animateNodes(); | ||
@@ -387,11 +420,15 @@ }, 5); | ||
key: 'getEdgeOffset', | ||
value: function getEdgeOffset(edge, node) { | ||
var offset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2]; | ||
value: function getEdgeOffset(node) { | ||
var offset = arguments.length <= 1 || arguments[1] === undefined ? { top: 0, left: 0 } : arguments[1]; | ||
// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested | ||
if (node) { | ||
var nodeOffset = { | ||
top: offset.top + node.offsetTop, | ||
left: offset.left + node.offsetLeft | ||
}; | ||
if (node.parentNode !== this.container) { | ||
return this.getEdgeOffset(edge, node.parentNode, offset + node['offset' + edge]); | ||
return this.getEdgeOffset(node.parentNode, nodeOffset); | ||
} else { | ||
return node['offset' + edge] + offset; | ||
return nodeOffset; | ||
} | ||
@@ -433,3 +470,4 @@ } | ||
value: function getLockPixelOffset(lockOffset) { | ||
var offset = lockOffset; | ||
var offsetX = lockOffset; | ||
var offsetY = lockOffset; | ||
var unit = 'px'; | ||
@@ -442,13 +480,17 @@ | ||
offset = parseFloat(lockOffset); | ||
offsetX = offsetY = parseFloat(lockOffset); | ||
unit = match[1]; | ||
} | ||
(0, _invariant2.default)(isFinite(offset), 'lockOffset value should be a finite. Given %s', lockOffset); | ||
(0, _invariant2.default)(isFinite(offsetX) && isFinite(offsetY), 'lockOffset value should be a finite. Given %s', lockOffset); | ||
if (unit === '%') { | ||
offset = offset * this.dimension / 100; | ||
offsetX = offsetX * this.width / 100; | ||
offsetY = offsetY * this.height / 100; | ||
} | ||
return offset; | ||
return { | ||
x: offsetX, | ||
y: offsetY | ||
}; | ||
} | ||
@@ -459,3 +501,2 @@ }, { | ||
var _props2 = this.props; | ||
var axis = _props2.axis; | ||
var lockAxis = _props2.lockAxis; | ||
@@ -469,5 +510,4 @@ var lockToContainerEdges = _props2.lockToContainerEdges; | ||
}; | ||
this.translate = translate; | ||
this.translate = translate[axis]; | ||
if (lockToContainerEdges) { | ||
@@ -481,6 +521,13 @@ var _getLockPixelOffsets = this.getLockPixelOffsets(); | ||
var minOffset = this.dimension / 2 - minLockOffset; | ||
var maxOffset = this.dimension / 2 - maxLockOffset; | ||
var minOffset = { | ||
x: this.halfWidth - minLockOffset.x, | ||
y: this.halfHeight - minLockOffset.y | ||
}; | ||
var maxOffset = { | ||
x: this.halfWidth - maxLockOffset.x, | ||
y: this.halfHeight - maxLockOffset.y | ||
}; | ||
translate[axis] = (0, _utils.limit)(this.minTranslate + minOffset, this.maxTranslate - maxOffset, translate[axis]); | ||
translate.x = (0, _utils.limit)(this.minTranslate.x + minOffset.x, this.maxTranslate.x - maxOffset.x, translate.x); | ||
translate.y = (0, _utils.limit)(this.minTranslate.y + minOffset.y, this.maxTranslate.y - maxOffset.y, translate.y); | ||
} | ||
@@ -503,3 +550,2 @@ | ||
var _props3 = this.props; | ||
var axis = _props3.axis; | ||
var transitionDuration = _props3.transitionDuration; | ||
@@ -509,4 +555,10 @@ var hideSortableGhost = _props3.hideSortableGhost; | ||
var nodes = this.manager.getOrderedRefs(); | ||
var deltaScroll = this.scrollContainer['scroll' + this.edge] - this.initialScroll; | ||
var sortingOffset = this.offsetEdge + this.translate + deltaScroll; | ||
var deltaScroll = { | ||
left: this.scrollContainer.scrollLeft - this.initialScroll.left, | ||
top: this.scrollContainer.scrollTop - this.initialScroll.top | ||
}; | ||
var sortingOffset = { | ||
left: this.offsetEdge.left + this.translate.x + deltaScroll.left, | ||
top: this.offsetEdge.top + this.translate.y + deltaScroll.top | ||
}; | ||
this.newIndex = null; | ||
@@ -520,13 +572,30 @@ | ||
var index = node.sortableInfo.index; | ||
var dimension = axis === 'x' ? node.offsetWidth : node.offsetHeight; | ||
var offset = this.dimension > dimension ? dimension / 2 : this.dimension / 2; | ||
var translate = 0; | ||
var translateX = 0; | ||
var translateY = 0; | ||
var width = node.offsetWidth; | ||
var halfWidth = width / 2; | ||
var height = node.offsetHeight; | ||
var halfHeight = height / 2; | ||
var offset = { | ||
width: this.width > width ? halfWidth : this.halfWidth, | ||
height: this.height > height ? halfHeight : this.halfHeight | ||
}; | ||
var translate = { | ||
x: 0, | ||
y: 0 | ||
}; | ||
// If we haven't cached the node's offsetTop / offsetLeft value | ||
if (edgeOffset == null) { | ||
nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(this.edge, node); | ||
if (!edgeOffset) { | ||
nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(node); | ||
} | ||
// Get a reference to the next and previous node | ||
var nextNode = i < nodes.length - 1 && nodes[i + 1]; | ||
var prevNode = i > 0 && nodes[i - 1]; | ||
// Also cache the next node's edge offset if needed. | ||
// We need this for calculating the animation in a grid setup | ||
if (nextNode && !nextNode.edgeOffset) { | ||
nextNode.edgeOffset = this.getEdgeOffset(nextNode.node); | ||
} | ||
// If the node is the one we're currently animating, skip it | ||
@@ -550,20 +619,55 @@ if (index === this.index) { | ||
if (index > this.index && sortingOffset + offset >= edgeOffset) { | ||
translate = -(this.dimension + this.marginOffset[axis]); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset <= edgeOffset + offset) { | ||
translate = this.dimension + this.marginOffset[axis]; | ||
if (this.newIndex == null) { | ||
if (this.axis.x) { | ||
if (this.axis.y) { | ||
// Calculations for a grid setup | ||
if (index < this.index && (sortingOffset.left - offset.width <= edgeOffset.left && sortingOffset.top <= edgeOffset.top + offset.height || sortingOffset.top + offset.height <= edgeOffset.top)) { | ||
// If the current node is to the left on the same row, or above the node that's being dragged | ||
// then move it to the right | ||
translate.x = this.width + this.marginOffset.x; | ||
if (edgeOffset.left + translate.x > this.containerBoundingRect.width - offset.width) { | ||
// If it moves passed the right bounds, then animate it to the first position of the next row. | ||
// We just use the offset of the next node to calculate where to move, because that node's original position | ||
// is exactly where we want to go | ||
translate.x = nextNode.edgeOffset.left - edgeOffset.left; | ||
translate.y = nextNode.edgeOffset.top - edgeOffset.top; | ||
} | ||
if (this.newIndex === null) { | ||
this.newIndex = index; | ||
} | ||
} else if (index > this.index && (sortingOffset.left + offset.width >= edgeOffset.left && sortingOffset.top + offset.height >= edgeOffset.top || sortingOffset.top + offset.height >= edgeOffset.top + height)) { | ||
// If the current node is to the right on the same row, or below the node that's being dragged | ||
// then move it to the left | ||
translate.x = -(this.width + this.marginOffset.x); | ||
if (edgeOffset.left + translate.x < this.containerBoundingRect.left + offset.width) { | ||
// If it moves passed the left bounds, then animate it to the last position of the previous row. | ||
// We just use the offset of the previous node to calculate where to move, because that node's original position | ||
// is exactly where we want to go | ||
translate.x = prevNode.edgeOffset.left - edgeOffset.left; | ||
translate.y = prevNode.edgeOffset.top - edgeOffset.top; | ||
} | ||
this.newIndex = index; | ||
} | ||
} else { | ||
if (index > this.index && sortingOffset.left + offset.width >= edgeOffset.left) { | ||
translate.x = -(this.width + this.marginOffset.x); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset.left <= edgeOffset.left + offset.width) { | ||
translate.x = this.width + this.marginOffset.x; | ||
if (this.newIndex == null) { | ||
this.newIndex = index; | ||
} | ||
} | ||
} | ||
} else if (this.axis.y) { | ||
if (index > this.index && sortingOffset.top + offset.height >= edgeOffset.top) { | ||
translate.y = -(this.height + this.marginOffset.y); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset.top <= edgeOffset.top + offset.height) { | ||
translate.y = this.height + this.marginOffset.y; | ||
if (this.newIndex == null) { | ||
this.newIndex = index; | ||
} | ||
} | ||
} | ||
if (axis === 'x') { | ||
translateX = translate; | ||
} else { | ||
translateY = translate; | ||
} | ||
node.style[_utils.vendorPrefix + 'Transform'] = 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'; | ||
node.style[_utils.vendorPrefix + 'Transform'] = 'translate3d(' + translate.x + 'px,' + translate.y + 'px,0)'; | ||
} | ||
@@ -615,3 +719,3 @@ | ||
}, _class.propTypes = { | ||
axis: _react.PropTypes.oneOf(['x', 'y']), | ||
axis: _react.PropTypes.oneOf(['x', 'y', 'xy']), | ||
distance: _react.PropTypes.number, | ||
@@ -618,0 +722,0 @@ lockAxis: _react.PropTypes.string, |
@@ -131,3 +131,6 @@ import _extends from 'babel-runtime/helpers/extends'; | ||
_this.margin = margin; | ||
_this.dimension = axis === 'x' ? _this.width : _this.height; | ||
_this.width = node.offsetWidth; | ||
_this.height = node.offsetHeight; | ||
_this.halfWidth = _this.width / 2; | ||
_this.halfHeight = _this.height / 2; | ||
_this.marginOffset = { | ||
@@ -138,9 +141,16 @@ x: _this.margin.left + _this.margin.right, | ||
_this.boundingClientRect = node.getBoundingClientRect(); | ||
_this.containerBoundingRect = containerBoundingRect; | ||
_this.index = index; | ||
_this.newIndex = index; | ||
var edge = _this.edge = axis === 'x' ? 'Left' : 'Top'; | ||
_this.offsetEdge = _this.getEdgeOffset(edge, node); | ||
_this.axis = { | ||
x: axis.indexOf('x') >= 0, | ||
y: axis.indexOf('y') >= 0 | ||
}; | ||
_this.offsetEdge = _this.getEdgeOffset(node); | ||
_this.initialOffset = _this.getOffset(e); | ||
_this.initialScroll = _this.scrollContainer['scroll' + edge]; | ||
_this.initialScroll = { | ||
top: _this.scrollContainer.scrollTop, | ||
left: _this.scrollContainer.scrollLeft | ||
}; | ||
@@ -159,9 +169,12 @@ _this.helper = _this.document.body.appendChild(node.cloneNode(true)); | ||
if (axis === 'x') { | ||
_this.minTranslate = (useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - _this.boundingClientRect.left - _this.width / 2; | ||
_this.maxTranslate = (useWindowAsScrollContainer ? _this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - _this.boundingClientRect.left - _this.width / 2; | ||
} else { | ||
_this.minTranslate = (useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - _this.boundingClientRect.top - _this.height / 2; | ||
_this.maxTranslate = (useWindowAsScrollContainer ? _this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - _this.boundingClientRect.top - _this.height / 2; | ||
_this.minTranslate = {}; | ||
_this.maxTranslate = {}; | ||
if (_this.axis.x) { | ||
_this.minTranslate.x = (useWindowAsScrollContainer ? 0 : containerBoundingRect.left) - _this.boundingClientRect.left - _this.halfWidth; | ||
_this.maxTranslate.x = (useWindowAsScrollContainer ? _this.contentWindow.innerWidth : containerBoundingRect.left + containerBoundingRect.width) - _this.boundingClientRect.left - _this.halfWidth; | ||
} | ||
if (_this.axis.y) { | ||
_this.minTranslate.y = (useWindowAsScrollContainer ? 0 : containerBoundingRect.top) - _this.boundingClientRect.top - _this.halfHeight; | ||
_this.maxTranslate.y = (useWindowAsScrollContainer ? _this.contentWindow.innerHeight : containerBoundingRect.top + containerBoundingRect.height) - _this.boundingClientRect.top - _this.halfHeight; | ||
} | ||
@@ -265,16 +278,31 @@ if (helperClass) { | ||
var translate = _this.translate; | ||
var direction = 0; | ||
var speed = 1; | ||
var acceleration = 10; | ||
var direction = { | ||
x: 0, | ||
y: 0 | ||
}; | ||
var speed = { | ||
x: 1, | ||
y: 1 | ||
}; | ||
var acceleration = { | ||
x: 10, | ||
y: 10 | ||
}; | ||
if (translate >= _this.maxTranslate - _this.dimension / 2) { | ||
direction = 1; // Scroll Down | ||
speed = acceleration * Math.abs((_this.maxTranslate - _this.dimension / 2 - translate) / _this.dimension); | ||
} else if (translate <= _this.minTranslate + _this.dimension / 2) { | ||
direction = -1; // Scroll Up | ||
speed = acceleration * Math.abs((translate - _this.dimension / 2 - _this.minTranslate) / _this.dimension); | ||
if (translate.y >= _this.maxTranslate.y - _this.halfHeight) { | ||
direction.y = 1; // Scroll Down | ||
speed.y = acceleration.y * Math.abs((_this.maxTranslate.y - _this.halfHeight - translate.y) / _this.height); | ||
} else if (translate.x >= _this.maxTranslate.x - _this.halfWidth) { | ||
direction.x = 1; // Scroll Right | ||
speed.x = acceleration.x * Math.abs((_this.maxTranslate.x - _this.halfWidth - translate.x) / _this.width); | ||
} else if (translate.y <= _this.minTranslate.y + _this.halfHeight) { | ||
direction.y = -1; // Scroll Up | ||
speed.y = acceleration.y * Math.abs((translate.y - _this.halfHeight - _this.minTranslate.y) / _this.height); | ||
} else if (translate.x <= _this.minTranslate.x + _this.halfWidth) { | ||
direction.x = -1; // Scroll Left | ||
speed.x = acceleration.x * Math.abs((translate.x - _this.halfWidth - _this.minTranslate.x) / _this.width); | ||
} | ||
if (_this.autoscrollInterval) { | ||
clearTimeout(_this.autoscrollInterval); | ||
clearInterval(_this.autoscrollInterval); | ||
_this.autoscrollInterval = null; | ||
@@ -284,8 +312,13 @@ _this.isAutoScrolling = false; | ||
if (direction !== 0) { | ||
if (direction.x !== 0 || direction.y !== 0) { | ||
_this.autoscrollInterval = setInterval(function () { | ||
_this.isAutoScrolling = true; | ||
var offset = 1 * speed * direction; | ||
_this.scrollContainer['scroll' + _this.edge] += offset; | ||
_this.translate += offset; | ||
var offset = { | ||
left: 1 * speed.x * direction.x, | ||
top: 1 * speed.y * direction.y | ||
}; | ||
_this.scrollContainer.scrollTop += offset.top; | ||
_this.scrollContainer.scrollLeft += offset.left; | ||
_this.translate.x += offset.left; | ||
_this.translate.y += offset.top; | ||
_this.animateNodes(); | ||
@@ -359,11 +392,15 @@ }, 5); | ||
key: 'getEdgeOffset', | ||
value: function getEdgeOffset(edge, node) { | ||
var offset = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2]; | ||
value: function getEdgeOffset(node) { | ||
var offset = arguments.length <= 1 || arguments[1] === undefined ? { top: 0, left: 0 } : arguments[1]; | ||
// Get the actual offsetTop / offsetLeft value, no matter how deep the node is nested | ||
if (node) { | ||
var nodeOffset = { | ||
top: offset.top + node.offsetTop, | ||
left: offset.left + node.offsetLeft | ||
}; | ||
if (node.parentNode !== this.container) { | ||
return this.getEdgeOffset(edge, node.parentNode, offset + node['offset' + edge]); | ||
return this.getEdgeOffset(node.parentNode, nodeOffset); | ||
} else { | ||
return node['offset' + edge] + offset; | ||
return nodeOffset; | ||
} | ||
@@ -405,3 +442,4 @@ } | ||
value: function getLockPixelOffset(lockOffset) { | ||
var offset = lockOffset; | ||
var offsetX = lockOffset; | ||
var offsetY = lockOffset; | ||
var unit = 'px'; | ||
@@ -414,13 +452,17 @@ | ||
offset = parseFloat(lockOffset); | ||
offsetX = offsetY = parseFloat(lockOffset); | ||
unit = match[1]; | ||
} | ||
invariant(isFinite(offset), 'lockOffset value should be a finite. Given %s', lockOffset); | ||
invariant(isFinite(offsetX) && isFinite(offsetY), 'lockOffset value should be a finite. Given %s', lockOffset); | ||
if (unit === '%') { | ||
offset = offset * this.dimension / 100; | ||
offsetX = offsetX * this.width / 100; | ||
offsetY = offsetY * this.height / 100; | ||
} | ||
return offset; | ||
return { | ||
x: offsetX, | ||
y: offsetY | ||
}; | ||
} | ||
@@ -431,3 +473,2 @@ }, { | ||
var _props2 = this.props; | ||
var axis = _props2.axis; | ||
var lockAxis = _props2.lockAxis; | ||
@@ -441,5 +482,4 @@ var lockToContainerEdges = _props2.lockToContainerEdges; | ||
}; | ||
this.translate = translate; | ||
this.translate = translate[axis]; | ||
if (lockToContainerEdges) { | ||
@@ -453,6 +493,13 @@ var _getLockPixelOffsets = this.getLockPixelOffsets(); | ||
var minOffset = this.dimension / 2 - minLockOffset; | ||
var maxOffset = this.dimension / 2 - maxLockOffset; | ||
var minOffset = { | ||
x: this.halfWidth - minLockOffset.x, | ||
y: this.halfHeight - minLockOffset.y | ||
}; | ||
var maxOffset = { | ||
x: this.halfWidth - maxLockOffset.x, | ||
y: this.halfHeight - maxLockOffset.y | ||
}; | ||
translate[axis] = limit(this.minTranslate + minOffset, this.maxTranslate - maxOffset, translate[axis]); | ||
translate.x = limit(this.minTranslate.x + minOffset.x, this.maxTranslate.x - maxOffset.x, translate.x); | ||
translate.y = limit(this.minTranslate.y + minOffset.y, this.maxTranslate.y - maxOffset.y, translate.y); | ||
} | ||
@@ -475,3 +522,2 @@ | ||
var _props3 = this.props; | ||
var axis = _props3.axis; | ||
var transitionDuration = _props3.transitionDuration; | ||
@@ -481,4 +527,10 @@ var hideSortableGhost = _props3.hideSortableGhost; | ||
var nodes = this.manager.getOrderedRefs(); | ||
var deltaScroll = this.scrollContainer['scroll' + this.edge] - this.initialScroll; | ||
var sortingOffset = this.offsetEdge + this.translate + deltaScroll; | ||
var deltaScroll = { | ||
left: this.scrollContainer.scrollLeft - this.initialScroll.left, | ||
top: this.scrollContainer.scrollTop - this.initialScroll.top | ||
}; | ||
var sortingOffset = { | ||
left: this.offsetEdge.left + this.translate.x + deltaScroll.left, | ||
top: this.offsetEdge.top + this.translate.y + deltaScroll.top | ||
}; | ||
this.newIndex = null; | ||
@@ -492,13 +544,30 @@ | ||
var index = node.sortableInfo.index; | ||
var dimension = axis === 'x' ? node.offsetWidth : node.offsetHeight; | ||
var offset = this.dimension > dimension ? dimension / 2 : this.dimension / 2; | ||
var translate = 0; | ||
var translateX = 0; | ||
var translateY = 0; | ||
var width = node.offsetWidth; | ||
var halfWidth = width / 2; | ||
var height = node.offsetHeight; | ||
var halfHeight = height / 2; | ||
var offset = { | ||
width: this.width > width ? halfWidth : this.halfWidth, | ||
height: this.height > height ? halfHeight : this.halfHeight | ||
}; | ||
var translate = { | ||
x: 0, | ||
y: 0 | ||
}; | ||
// If we haven't cached the node's offsetTop / offsetLeft value | ||
if (edgeOffset == null) { | ||
nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(this.edge, node); | ||
if (!edgeOffset) { | ||
nodes[i].edgeOffset = edgeOffset = this.getEdgeOffset(node); | ||
} | ||
// Get a reference to the next and previous node | ||
var nextNode = i < nodes.length - 1 && nodes[i + 1]; | ||
var prevNode = i > 0 && nodes[i - 1]; | ||
// Also cache the next node's edge offset if needed. | ||
// We need this for calculating the animation in a grid setup | ||
if (nextNode && !nextNode.edgeOffset) { | ||
nextNode.edgeOffset = this.getEdgeOffset(nextNode.node); | ||
} | ||
// If the node is the one we're currently animating, skip it | ||
@@ -522,20 +591,55 @@ if (index === this.index) { | ||
if (index > this.index && sortingOffset + offset >= edgeOffset) { | ||
translate = -(this.dimension + this.marginOffset[axis]); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset <= edgeOffset + offset) { | ||
translate = this.dimension + this.marginOffset[axis]; | ||
if (this.newIndex == null) { | ||
if (this.axis.x) { | ||
if (this.axis.y) { | ||
// Calculations for a grid setup | ||
if (index < this.index && (sortingOffset.left - offset.width <= edgeOffset.left && sortingOffset.top <= edgeOffset.top + offset.height || sortingOffset.top + offset.height <= edgeOffset.top)) { | ||
// If the current node is to the left on the same row, or above the node that's being dragged | ||
// then move it to the right | ||
translate.x = this.width + this.marginOffset.x; | ||
if (edgeOffset.left + translate.x > this.containerBoundingRect.width - offset.width) { | ||
// If it moves passed the right bounds, then animate it to the first position of the next row. | ||
// We just use the offset of the next node to calculate where to move, because that node's original position | ||
// is exactly where we want to go | ||
translate.x = nextNode.edgeOffset.left - edgeOffset.left; | ||
translate.y = nextNode.edgeOffset.top - edgeOffset.top; | ||
} | ||
if (this.newIndex === null) { | ||
this.newIndex = index; | ||
} | ||
} else if (index > this.index && (sortingOffset.left + offset.width >= edgeOffset.left && sortingOffset.top + offset.height >= edgeOffset.top || sortingOffset.top + offset.height >= edgeOffset.top + height)) { | ||
// If the current node is to the right on the same row, or below the node that's being dragged | ||
// then move it to the left | ||
translate.x = -(this.width + this.marginOffset.x); | ||
if (edgeOffset.left + translate.x < this.containerBoundingRect.left + offset.width) { | ||
// If it moves passed the left bounds, then animate it to the last position of the previous row. | ||
// We just use the offset of the previous node to calculate where to move, because that node's original position | ||
// is exactly where we want to go | ||
translate.x = prevNode.edgeOffset.left - edgeOffset.left; | ||
translate.y = prevNode.edgeOffset.top - edgeOffset.top; | ||
} | ||
this.newIndex = index; | ||
} | ||
} else { | ||
if (index > this.index && sortingOffset.left + offset.width >= edgeOffset.left) { | ||
translate.x = -(this.width + this.marginOffset.x); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset.left <= edgeOffset.left + offset.width) { | ||
translate.x = this.width + this.marginOffset.x; | ||
if (this.newIndex == null) { | ||
this.newIndex = index; | ||
} | ||
} | ||
} | ||
} else if (this.axis.y) { | ||
if (index > this.index && sortingOffset.top + offset.height >= edgeOffset.top) { | ||
translate.y = -(this.height + this.marginOffset.y); | ||
this.newIndex = index; | ||
} else if (index < this.index && sortingOffset.top <= edgeOffset.top + offset.height) { | ||
translate.y = this.height + this.marginOffset.y; | ||
if (this.newIndex == null) { | ||
this.newIndex = index; | ||
} | ||
} | ||
} | ||
if (axis === 'x') { | ||
translateX = translate; | ||
} else { | ||
translateY = translate; | ||
} | ||
node.style[vendorPrefix + 'Transform'] = 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'; | ||
node.style[vendorPrefix + 'Transform'] = 'translate3d(' + translate.x + 'px,' + translate.y + 'px,0)'; | ||
} | ||
@@ -587,3 +691,3 @@ | ||
}, _class.propTypes = { | ||
axis: PropTypes.oneOf(['x', 'y']), | ||
axis: PropTypes.oneOf(['x', 'y', 'xy']), | ||
distance: PropTypes.number, | ||
@@ -590,0 +694,0 @@ lockAxis: PropTypes.string, |
{ | ||
"name": "react-sortable-hoc", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "Set of higher-order components to turn any list into a sortable, touch-friendly, animated list", | ||
@@ -93,2 +93,3 @@ "author": { | ||
"react": "^15.2.1", | ||
"react-dom": "^15.2.1", | ||
"react-addons-pure-render-mixin": "^15.0.2", | ||
@@ -95,0 +96,0 @@ "react-addons-shallow-compare": "^15.1.0", |
@@ -18,3 +18,3 @@ # React Sortable (HOC) | ||
* **Works with React Virtualized, React-Infinite, etc.** | ||
* **Horizontal or vertical lists** โ โ | ||
* **Horizontal lists, vertical lists, or a grid** โ โ โคก | ||
* **Touch support** ๐ | ||
@@ -104,3 +104,3 @@ | ||
|:---------------------------|:------------------|:-----------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| axis | String | `y` | The axis you want to sort on, either 'x' or 'y' | | ||
| axis | String | `y` | Items can be sorted horizontally, vertically or in a grid. Possible values: `x`, `y` or `xy` | | ||
| lockAxis | String | | If you'd like, you can lock movement to an axis while sorting. This is not something that is possible with HTML5 Drag & Drop | | ||
@@ -137,2 +137,12 @@ | helperClass | String | | You can provide a class you'd like to add to the sortable helper to add some styles to it | | ||
FAQ | ||
--------------- | ||
### Grid support | ||
Need to sort items in a grid? We've got you covered! Just set the `axis` prop to `xy`. Grid support is currently limited to a setup where all the cells in the grid have the same width and height, though we're working hard to get variable width support in the near future. | ||
### Item disappearing when sorting / CSS issues | ||
Upon sorting, `react-sortable-hoc` creates a clone of the element you are sorting (the _sortable-helper_) and appends it to the end of the `<body>` tag. The original element will still be in-place to preserve its position in the DOM until the end of the drag (with inline-styling to make it invisible). If the _sortable-helper_ gets messed up from a CSS standpoint, consider that maybe your selectors to the draggable item are dependent on a parent element which isn't present anymore (again, since the _sortable-helper_ is at the end of the `<body>`). | ||
Dependencies | ||
@@ -150,9 +160,2 @@ ------------ | ||
Common Pitfalls | ||
--------------- | ||
### CSS messing up on drag? | ||
Upon sorting, `react-sortable-hoc` creates a clone of the element you are sorting (the _sortable-helper_) and appends it to the end of the `<body>` tag. The original element will still be in-place to preserve its position in the DOM until the end of the drag (with inline-styling to make it invisible). If the _sortable-helper_ gets messed up from a CSS standpoint, consider that maybe your selectors to the draggable item are dependent on a parent element which isn't present anymore (again, since the _sortable-helper_ is at the end of the `<body>`). | ||
Contributions | ||
@@ -159,0 +162,0 @@ ------------ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1008286
8693
169
50