react-window-sortable
Version:
React Window Sortable is an HOC for react-window that allows drag and drop sorting of lists
400 lines (399 loc) • 12.8 kB
JavaScript
var __extends =
(this && this.__extends) ||
(function () {
var extendStatics = function (d, b) {
extendStatics =
Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array &&
function (d, b) {
d.__proto__ = b;
}) ||
function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype =
b === null
? Object.create(b)
: ((__.prototype = b.prototype), new __());
};
})();
var __assign =
(this && this.__assign) ||
function () {
__assign =
Object.assign ||
function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest =
(this && this.__rest) ||
function (s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (
e.indexOf(p[i]) < 0 &&
Object.prototype.propertyIsEnumerable.call(s, p[i])
)
t[p[i]] = s[p[i]];
}
return t;
};
import * as React from "react";
import { VariableSizeList } from "react-window";
import { createRef, useContext } from "react";
import { Child } from "./Child";
import { DraggingElement } from "../../src/sortable-list/DraggingElement";
import { DropZoneElement } from "../../src/sortable-list/DropZoneElement";
export var SortableFixedSizeList = React.forwardRef(function (props, ref) {
var itemSize = props.itemSize,
rest = __rest(props, ["itemSize"]);
return React.createElement(
SortableVariableSizeList,
__assign(
{
ref: ref,
itemSize: function () {
return itemSize;
},
},
rest
)
);
});
var SortableVariableSizeList = /** @class */ (function (_super) {
__extends(SortableVariableSizeList, _super);
function SortableVariableSizeList(props) {
var _this = _super.call(this, props) || this;
_this.dragRef = createRef();
_this.dropZoneRef = createRef();
_this.listRef = createRef();
_this.startClientY = 0;
_this.startDragObjOffsetY = 0;
_this.hoverIndex = null;
_this.autoScroll = "none";
_this.autoScrollTimer = null;
_this.sortableContext = {
Child: _this.props.children,
itemKey: _this.props.itemKey,
onMouseDown: _this.mouseDown.bind(_this),
};
_this.dragContext = null;
_this.state = {
dragging: null,
};
_this.onMouseUp = _this.onMouseUp.bind(_this);
_this.onMouseMove = _this.onMouseMove.bind(_this);
_this.mouseDown = _this.mouseDown.bind(_this);
return _this;
}
SortableVariableSizeList.prototype.getAutoScrollWhenDistanceLessThan = function () {
return this.props.autoScrollWhenDistanceLessThan || 50;
};
SortableVariableSizeList.prototype.getAutoScrollSpeed = function () {
return this.props.autoScrollSpeed || 50;
};
SortableVariableSizeList.prototype.componentWillUnmount = function () {
document.body.removeEventListener("mouseup", this.onMouseUp);
document.body.removeEventListener("mousemove", this.onMouseMove);
this.setAutoScroll("none", 0);
};
SortableVariableSizeList.prototype.mouseDown = function (e, params) {
console.log("mouse down", params.index);
var list = this.listRef.current;
if (list === null) return;
this.startClientY = e.clientY;
var top = parseInt((params.style.top || "0").toString(), 10);
this.startDragObjOffsetY = top - this.getScrollOffsetTop(list);
document.body.addEventListener("mouseup", this.onMouseUp);
document.body.addEventListener("mousemove", this.onMouseMove);
this.setState({
dragging: params,
});
};
SortableVariableSizeList.prototype.onMouseMove = function (event) {
this.updateDragElementPositioning(event.clientY);
this.checkAutoScroll(event.clientY);
};
SortableVariableSizeList.prototype.updateDragElementPositioning = function (
mouseY
) {
var dragRef = this.dragRef.current;
if (dragRef === null) return;
if (this.listRef.current === null) return;
var scrollOffsetTop = this.getScrollOffsetTop(this.listRef.current);
var dY = mouseY - this.startClientY;
var newY = this.startDragObjOffsetY + dY + scrollOffsetTop;
dragRef.style.top = newY + "px";
var dropRef = this.dropZoneRef.current;
if (dropRef === null) return;
var _a = this.getHoverDetails(newY),
offsetTop = _a.offsetTop,
index = _a.index;
this.hoverIndex = index;
dropRef.style.top = offsetTop + "px";
};
SortableVariableSizeList.prototype.getHoverDetails = function (offsetY) {
var posY = 0;
for (var i = 0; i < this.props.itemCount; i++) {
var height = this.props.itemSize(i);
if (offsetY < posY + height) {
return {
offsetTop: posY,
index: i,
};
}
posY += height;
}
return {
offsetTop: posY,
index: this.props.itemCount - 1,
};
};
SortableVariableSizeList.prototype.getScrollOffsetTop = function (list) {
return this.getScrollRef(list).scrollTop;
};
SortableVariableSizeList.prototype.getScrollRef = function (list) {
// @ts-ignore dangerously reach into list internals, so we can get a ref on the scroll element
return list._outerRef;
};
SortableVariableSizeList.prototype.checkAutoScroll = function (mouseY) {
if (this.listRef.current === null) return;
var list = this.listRef.current;
var scrollRef = this.getScrollRef(list);
var rect = scrollRef.getBoundingClientRect();
var listTop = rect.y;
var listBottom = rect.y + rect.height;
var buffer = this.getAutoScrollWhenDistanceLessThan();
if (mouseY - listTop < buffer) {
this.setAutoScroll("up", mouseY);
} else if (listBottom - mouseY < this.getAutoScrollWhenDistanceLessThan()) {
this.setAutoScroll("down", mouseY);
} else {
this.setAutoScroll("none", mouseY);
}
};
SortableVariableSizeList.prototype.setAutoScroll = function (scroll, mouseY) {
var _this = this;
if (this.autoScrollTimer !== null) {
clearInterval(this.autoScrollTimer);
this.autoScrollTimer = null;
}
this.autoScroll = scroll;
if (scroll === "none") return;
if (this.dragRef.current === null) return;
if (this.listRef.current === null) return;
var delta = this.getAutoScrollSpeed();
if (scroll === "up") {
delta = delta * -1;
}
this.autoScrollTimer = setInterval(function (e) {
if (_this.listRef.current === null) return;
var offsetTop = _this.getScrollOffsetTop(_this.listRef.current);
var newOffsetTop = offsetTop + delta;
_this.listRef.current.scrollTo(newOffsetTop);
_this.updateDragElementPositioning(mouseY);
}, 100);
};
SortableVariableSizeList.prototype.onMouseUp = function () {
document.body.removeEventListener("mouseup", this.onMouseUp);
document.body.removeEventListener("mousemove", this.onMouseMove);
this.setAutoScroll("none", 0);
if (this.state.dragging === null) return;
var startIndex = this.state.dragging.index;
this.setState({
dragging: null,
});
if (this.hoverIndex !== null) {
var newIndex = this.hoverIndex;
if (newIndex > startIndex) {
newIndex = Math.max(0, newIndex - 1);
}
this.props.onSortOrderChanged({
originalIndex: startIndex,
newIndex: newIndex,
});
}
this.hoverIndex = null;
};
SortableVariableSizeList.prototype.renderDropZoneElement = function () {
if (this.state.dragging === null) return;
var style = Object.assign({}, this.state.dragging.style, {
display: "flex",
flexDirection: "row",
alignItems: "stretch",
zIndex: 2,
background: "white",
});
var dropElement =
this.props.dropElement ||
React.createElement("div", {
style: {
border: "2px dashed #0087F7",
borderRadius: "3px",
margin: "2px",
flex: 1,
boxSizing: "border-box",
},
});
return React.createElement(
"div",
{ ref: this.dropZoneRef, style: style },
dropElement
);
};
SortableVariableSizeList.prototype.renderDraggingElement = function () {
if (this.state.dragging === null) return null;
var _a = this.state.dragging,
style = _a.style,
rest = __rest(_a, ["style"]);
var Child = this.props.children;
style = Object.assign(
{},
style,
{
boxShadow: "1px 1px 5px 0px hsla(0, 0%, 0%, 0.31)",
zIndex: 3,
},
this.props.draggingElementStyle || {}
);
if (!style.backgroundColor) style.backgroundColor = "white";
return React.createElement(
Child,
__assign({ ref: this.dragRef }, rest, {
className: this.props.draggingElementClassName,
style: style,
onSortMouseDown: function (e) {},
})
);
};
SortableVariableSizeList.prototype.renderInnerElement = function () {
var _this = this;
var InnerElement = this.props.innerElementType;
return React.forwardRef(function (_a, ref) {
var children = _a.children,
rest = __rest(_a, ["children"]);
var inner = React.createElement(
React.Fragment,
null,
children,
_this.renderDraggingElement(),
_this.renderDropZoneElement()
);
if (InnerElement) {
return React.createElement(
InnerElement,
__assign({}, rest, { ref: ref }),
inner
);
}
return React.createElement(
"div",
__assign({}, rest, { ref: ref }),
inner
);
});
};
SortableVariableSizeList.prototype.getSortableContext = function () {
var value = {
Child: this.props.children,
itemKey: this.props.itemKey,
onMouseDown: this.mouseDown,
};
if (value.Child === this.sortableContext.Child) {
if (value.itemKey === this.sortableContext.itemKey) {
return this.sortableContext;
}
}
this.sortableContext = value;
return this.sortableContext;
};
SortableVariableSizeList.prototype.getDragContext = function () {
if (!this.state.dragging) return null;
var value = {
dragging: this.state.dragging,
dragRef: this.dragRef,
dropZoneRef: this.dropZoneRef,
Child: this.props.children,
};
if (
this.dragContext === null ||
this.dragContext.dragging !== value.dragging ||
this.dragContext.Child !== value.Child
) {
this.dragContext = value;
}
return this.dragContext;
};
SortableVariableSizeList.prototype.render = function () {
var _a = this.props,
children = _a.children,
innerElementType = _a.innerElementType,
props = __rest(_a, ["children", "innerElementType"]);
return React.createElement(
SortableContext.Provider,
{ value: this.getSortableContext() },
React.createElement(
InnerElementContext.Provider,
{ value: this.props.innerElementType },
React.createElement(
DragContext.Provider,
{ value: this.getDragContext() },
React.createElement(
VariableSizeList,
__assign(
{ ref: this.listRef, innerElementType: InnerElementType },
props
),
Child
)
)
)
);
};
return SortableVariableSizeList;
})(React.Component);
export { SortableVariableSizeList };
export var SortableContext = React.createContext({
Child: function () {
return React.createElement("div", null);
},
onMouseDown: function () {},
itemKey: undefined,
});
export var DragContext = React.createContext(null);
var InnerElementContext = React.createContext(undefined);
function InnerElementType(props) {
var children = props.children,
rest = __rest(props, ["children"]);
var InnerElement = useContext(InnerElementContext);
var inner = React.createElement(
React.Fragment,
null,
children,
React.createElement(DraggingElement, null),
React.createElement(DropZoneElement, null)
);
if (InnerElement) {
return React.createElement(InnerElement, __assign({}, rest), inner);
}
return React.createElement("div", __assign({}, rest), inner);
}
//# sourceMappingURL=index.js.map