diff --git a/README.md b/README.md index 13f12281a..7d2957812 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ There are already a number of great Drag & Drop libraries out there (for instanc | getHelperDimensions | Function | [Function](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/index.js#L74-L77) | Optional `function({node, index, collection})` that should return the computed dimensions of the SortableHelper. See [default implementation](https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableContainer/defaultGetHelperDimensions.js) for more details | | helperContainer | HTMLElement | Function | `document.body` | By default, the cloned sortable helper is appended to the document body. Use this prop to specify a different container for the sortable clone to be appended to. Accepts an `HTMLElement` or a function returning an `HTMLElement` that will be invoked before right before sorting begins | | disableAutoscroll | Boolean | `false` | Disables autoscrolling while dragging | +| rtl | Boolean | `false` | If the direction of page or container is "RTL", the "rtl" props must be `true`. | \* `OffsetValue` can either be a finite `Number` or a `String` made up of a number and a unit (`px` or `%`). Examples: `10` (which is the same as `"10px"`), `"50%"` diff --git a/src/AutoScroller/index.js b/src/AutoScroller/index.js index 6f03bde34..9fccbfbe6 100644 --- a/src/AutoScroller/index.js +++ b/src/AutoScroller/index.js @@ -13,7 +13,7 @@ export default class AutoScroller { this.interval = null; } - update({translate, minTranslate, maxTranslate, width, height}) { + update({translate, minTranslate, maxTranslate, width, height, rtl = false}) { const direction = { x: 0, y: 0, @@ -38,8 +38,8 @@ export default class AutoScroller { const isTop = scrollTop === 0; const isBottom = scrollHeight - scrollTop - clientHeight === 0; - const isLeft = scrollLeft === 0; - const isRight = scrollWidth - scrollLeft - clientWidth === 0; + const isLeft = scrollLeft === (!rtl ? 0 : clientWidth - scrollWidth); + const isRight = scrollLeft === (!rtl ? scrollWidth - clientWidth : 0); if (translate.y >= maxTranslate.y - height / 2 && !isBottom) { // Scroll Down diff --git a/src/SortableContainer/index.js b/src/SortableContainer/index.js index 9b24a0456..64b12d9be 100644 --- a/src/SortableContainer/index.js +++ b/src/SortableContainer/index.js @@ -620,7 +620,7 @@ export default function sortableContainer( } animateNodes() { - const {transitionDuration, hideSortableGhost, onSortOver} = this.props; + const {rtl, transitionDuration, hideSortableGhost, onSortOver} = this.props; const {containerScrollDelta, windowScrollDelta} = this; const nodes = this.manager.getOrderedRefs(); const sortingOffset = { @@ -706,14 +706,19 @@ export default function sortableContainer( setTransitionDuration(node, transitionDuration); } + const translateXFactor = rtl ? -1 : 1; + if (this.axis.x) { if (this.axis.y) { // Calculations for a grid setup if ( mustShiftForward || (index < this.index && - ((sortingOffset.left + windowScrollDelta.left - offset.width <= - edgeOffset.left && + ((( + (!rtl && (sortingOffset.left + windowScrollDelta.left - offset.width <= edgeOffset.left)) + || + (rtl && (sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left)) + ) && sortingOffset.top + windowScrollDelta.top <= edgeOffset.top + offset.height) || sortingOffset.top + windowScrollDelta.top + offset.height <= @@ -721,10 +726,11 @@ export default function sortableContainer( ) { // 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; + translate.x = translateXFactor * (this.width + this.marginOffset.x); if ( - edgeOffset.left + translate.x > - this.containerBoundingRect.width - offset.width * 2 + (!rtl && (edgeOffset.left + translate.x > this.containerBoundingRect.width - offset.width * 2)) + || + (rtl && edgeOffset.left + translate.x < this.containerBoundingRect.left + 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 @@ -740,8 +746,11 @@ export default function sortableContainer( } else if ( mustShiftBackward || (index > this.index && - ((sortingOffset.left + windowScrollDelta.left + offset.width >= - edgeOffset.left && + ((( + (!rtl && (sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left)) + || + (rtl && (sortingOffset.left + windowScrollDelta.left - offset.width <= edgeOffset.left)) + ) && sortingOffset.top + windowScrollDelta.top + offset.height >= edgeOffset.top) || sortingOffset.top + windowScrollDelta.top + offset.height >= @@ -749,10 +758,11 @@ export default function sortableContainer( ) { // 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); + translate.x = - 1 * translateXFactor * (this.width + this.marginOffset.x); if ( - edgeOffset.left + translate.x < - this.containerBoundingRect.left + offset.width + (!rtl && (edgeOffset.left + translate.x < this.containerBoundingRect.left + offset.width)) + || + (rtl && (edgeOffset.left + translate.x > this.containerBoundingRect.width - this.containerBoundingRect.left - offset.width * 2)) ) { // 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 @@ -768,18 +778,26 @@ export default function sortableContainer( if ( mustShiftBackward || (index > this.index && - sortingOffset.left + windowScrollDelta.left + offset.width >= - edgeOffset.left) + ( + (!rtl && (sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left)) + || + (rtl && (sortingOffset.left + windowScrollDelta.left - offset.width <= edgeOffset.left)) + ) + ) ) { - translate.x = -(this.width + this.marginOffset.x); + translate.x = -1 * translateXFactor * (this.width + this.marginOffset.x); this.newIndex = index; } else if ( mustShiftForward || (index < this.index && - sortingOffset.left + windowScrollDelta.left <= - edgeOffset.left + offset.width) + ( + (!rtl && (sortingOffset.left + windowScrollDelta.left - offset.width <= edgeOffset.left)) + || + (rtl && (sortingOffset.left + windowScrollDelta.left + offset.width >= edgeOffset.left)) + ) + ) ) { - translate.x = this.width + this.marginOffset.x; + translate.x = translateXFactor * (this.width + this.marginOffset.x); if (this.newIndex == null) { this.newIndex = index; @@ -879,6 +897,7 @@ export default function sortableContainer( minTranslate: this.minTranslate, translate: this.translate, width: this.width, + rtl: this.props.rtl }); }; @@ -963,6 +982,9 @@ export default function sortableContainer( }; keyMove = (shift) => { + if (this.props.rtl && this.props.axis.indexOf('x') !== -1) { + shift = -1 * shift; + } const nodes = this.manager.getOrderedRefs(); const {index: lastIndex} = nodes[nodes.length - 1].node.sortableInfo; const newIndex = this.newIndex + shift; diff --git a/src/SortableContainer/props.js b/src/SortableContainer/props.js index ba714b48a..3c7efa1fb 100644 --- a/src/SortableContainer/props.js +++ b/src/SortableContainer/props.js @@ -6,6 +6,7 @@ import defaultGetHelperDimensions from './defaultGetHelperDimensions'; import defaultShouldCancelStart from './defaultShouldCancelStart'; export const propTypes = { + rtl: PropTypes.bool, axis: PropTypes.oneOf(['x', 'y', 'xy']), contentWindow: PropTypes.any, disableAutoscroll: PropTypes.bool, @@ -59,6 +60,7 @@ export const defaultKeyCodes = { }; export const defaultProps = { + rtl: false, axis: 'y', disableAutoscroll: false, distance: 0,