@amaui/ui-react
Version:
UI for React
164 lines (163 loc) • 11.3 kB
JavaScript
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;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const utils_1 = require("@amaui/utils");
const style_react_1 = require("@amaui/style-react");
const useStyle = (0, style_react_1.style)(theme => ({
root: {}
}), { name: 'amaui-DragAndDropList' });
const DragAndDropList = react_1.default.forwardRef((props_, ref) => {
const theme = (0, style_react_1.useAmauiTheme)();
const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiDragAndDropList) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]);
const { onChange: onChange_, items, image, delay = 0, precise = true, draggedIsElement = true, isEqual, getDraggingElement, onDraggedElement, onDragStart: onDragStart_, className, children } = props, other = __rest(props, ["onChange", "items", "image", "delay", "precise", "draggedIsElement", "isEqual", "getDraggingElement", "onDraggedElement", "onDragStart", "className", "children"]);
const { classes } = useStyle();
const refs = {
root: react_1.default.useRef(undefined),
dragging: react_1.default.useRef(undefined),
rectDragged: react_1.default.useRef(undefined),
isDragging: react_1.default.useRef(),
previous: react_1.default.useRef(undefined)
};
const onChange = react_1.default.useMemo(() => {
return (0, utils_1.debounce)((indexPrevious, indexNew) => onChange_(indexPrevious, indexNew), delay);
}, [onChange_, delay]);
react_1.default.useEffect(() => {
var _a;
const onMouseUp = (event) => {
// in use case
// where onDragEnd is never emited
// due to original element having it
// has been removed from the dom
// prior to onDragEnd event is to be emited
// alternative way to provide a callback
// to dragging has ended
if (refs.isDragging.current) {
if ((0, utils_1.is)('function', onDraggedElement))
onDraggedElement(null);
refs.isDragging.current = false;
}
};
const rootDocument = (0, utils_1.isEnvironment)('browser') ? (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document) : undefined;
rootDocument.body.addEventListener('mouseup', onMouseUp);
rootDocument.body.addEventListener('touchend', onMouseUp);
return () => {
rootDocument.body.removeEventListener('mouseup', onMouseUp);
rootDocument.body.removeEventListener('touchend', onMouseUp);
};
}, [onDraggedElement]);
const img = react_1.default.useMemo(() => {
var _a;
const rootDocument = (0, utils_1.isEnvironment)('browser') ? (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document) : undefined;
const element = rootDocument.createElement('img');
element.src = (0, utils_1.is)('string', image) ? image : `data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAWAC8DAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKACgAoAKACgD8gtF+E3xs1/wD4UzrXiHxZ+1dZaj43/au+P/gj4r2Vt8RPjBo1np/7PsfiP42654IE+mxalFB4H8OzzeGvAlr4Z+IWjReH9dbQvE1noei+K10q+8N29l/LWD4Z4vx3+qeLx+Z+JdGvnHiXxvk/E1KGe8VYSlQ4Hjj+L8Zk/Ph44iMMnwM55fk1PL89wkcDjXgswpYPCZksNWwFOj7cq2Hj7eMYYNqng8NUot0qEm8Ty4eNSzt+8klOo50pc0eaDlKHMptyG2+Kml/8Id4f+NFz+1o3wN8JeLf2t/DOnan8MZPjbffFG81Xw18aYdI/Zw1Hx1rHw5gm+K3ijwpdfC9dUuvBvie/uNV8M+JdZh0bVvGt5f2cun3V3Tp8SYb+ysDxbU8TnwdlmaeJ+X0MRw7Li+txHVxOX8XRwvANfOcVkMJcS5jltThxYirlOY16mJy/MMXHCYrN61alKhUql6L55UFgvrE4YKbVX6uqKU6HNilTjVfsYTVaynBJThHmjTSd0ptK039seDSvhH8P/FN18ZH1L9pXwD8JdH8f+OdNu9WnufgFrHwx8RSXnxN1TVNb0O9m0r4ceJ/ir8GbnTdIju9Ney0+f4saPfXtl9o1TUbt5LwtDxVhhuF8jzKpxY8R4gZLwxhc7zihUxM6nBOK4ex0qvEOIxOMwdaeGyHMeJeFKmHwsauHlRoT4lwtatS58RXq8yk8C3WqQVC2FqVpU6bStiY1Y2pJRkr1YUa6crO79jJJ6JE/wmtf2kZv2kLEeLNa+Ltj4lX43/E678cx3+j/ABs1D4UXvwTsz44i8Eabpdxq+saZ+znYeGbvSJ/CR8Lal4I0i7+Ky+K4x/wkti8Uviq/t74Yp8fS4+o/2ni+KKOYLi/iKrnMa+F4vr8M1eEaTziOT4fDTxWKw/AdDL6mFnln9m4jJ8NV4lWZR/4UKLjLMq1MrPC/VXyRoOH1ekqdpYdVliH7P2jajF4pzUufnVSSo8nwP4E/1sr+nTxQoAKACgAoAKACgAD/2Q==`;
return element;
}, []);
const onDragStart = (item) => async (event) => {
var _a;
event.dataTransfer.setData('text', (item === null || item === void 0 ? void 0 : item.value) !== undefined ? item.value : item);
if (image)
event.dataTransfer.setDragImage(img, 0, 0);
refs.isDragging.current = true;
const dragging = (0, utils_1.is)('function', getDraggingElement) ? getDraggingElement(event) : event.target;
if (onDragStart_)
onDragStart_(item, event);
refs.dragging.current = draggedIsElement ? dragging : (_a = dragging === null || dragging === void 0 ? void 0 : dragging.dataset) === null || _a === void 0 ? void 0 : _a.amauiDragAndDropListValue;
refs.rectDragged.current = {
height: dragging.clientHeight,
x: event.clientX - dragging.offsetLeft,
y: event.clientY - dragging.offsetTop,
};
setTimeout(() => {
if ((0, utils_1.is)('function', onDraggedElement))
onDraggedElement === null || onDraggedElement === void 0 ? void 0 : onDraggedElement(item);
});
};
const onDragEnd = () => (event) => {
// clean up
refs.isDragging.current = false;
refs.rectDragged.current = null;
refs.dragging.current = null;
if ((0, utils_1.is)('function', onDraggedElement))
onDraggedElement(null);
};
const onDragOver = () => (event) => {
var _a;
event.preventDefault();
const rootDocument = (0, utils_1.isEnvironment)('browser') ? (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document) : undefined;
const over = event.currentTarget;
const dragging = draggedIsElement ? refs.dragging.current : rootDocument.body.querySelector(`[data-amaui-drag-and-drop-list-value="${refs.dragging.current}"]`);
if (!(over && dragging))
return;
if (precise) {
if (over !== dragging) {
const rectOver = {
height: over.clientHeight,
x: over.offsetLeft,
y: over.offsetTop
};
const mousePosition = {
x: event.clientX - rectOver.x,
y: event.clientY - rectOver.y
};
const partBottom = Math.abs(refs.rectDragged.current.height - refs.rectDragged.current.y);
const partTop = refs.rectDragged.current.y;
const half = rectOver.height / 2;
const positionTopBottom = (partBottom + mousePosition.y) >= half ? 'bottom' : 'top';
const positionBottomTop = (mousePosition.y - partTop) <= half ? 'top' : 'bottom';
const overIndex = items.findIndex((item) => isEqual ? isEqual(item, over.dataset.amauiDragAndDropListValue) : item === over.dataset.amauiDragAndDropListValue);
const draggedIndex = items.findIndex((item) => isEqual ? isEqual(item, dragging.dataset.amauiDragAndDropListValue) : item === dragging.dataset.amauiDragAndDropListValue);
// if dragged is above over & bottom swap their indexes
// if dragged is below over && top swap their indexes
if ((draggedIndex < overIndex && positionTopBottom === 'bottom') ||
(draggedIndex > overIndex && positionBottomTop === 'top')) {
if (!refs.previous.current || !(0, utils_1.equalDeep)(refs.previous.current, [draggedIndex, overIndex])) {
onChange(draggedIndex, overIndex);
refs.previous.current = [draggedIndex, overIndex];
}
}
}
}
else {
const overIndex = items.findIndex((item) => isEqual ? isEqual(item, over.dataset.amauiDragAndDropListValue) : item === over.dataset.amauiDragAndDropListValue);
const draggedIndex = items.findIndex((item) => isEqual ? isEqual(item, dragging.dataset.amauiDragAndDropListValue) : item === dragging.dataset.amauiDragAndDropListValue);
if (!refs.previous.current || !(0, utils_1.equalDeep)(refs.previous.current, [draggedIndex, overIndex])) {
if ((0, utils_1.is)('function', onChange))
onChange(draggedIndex, overIndex);
refs.previous.current = [draggedIndex, overIndex];
}
}
};
if ((0, utils_1.is)('function', children))
return children({
ref: item => {
if (ref) {
if ((0, utils_1.is)('function', ref))
ref(item);
else
ref.current = item;
}
refs.root.current = item;
},
onDragStart,
onDragOver,
onDragEnd
});
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
});
DragAndDropList.displayName = 'amaui-DragAndDropList';
exports.default = DragAndDropList;
;