linkmore-design
Version:
🌈 🚀lm组件库。🚀
637 lines (629 loc) • 23.6 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
var _excluded = ["children", "columns", "disabled", "id", "items", "style"];
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { closestCenter, pointerWithin,
// 返回指针悬停在其上的矩形
rectIntersection, DndContext, DragOverlay,
// DropAnimation,
getFirstCollision, KeyboardSensor, MouseSensor, TouchSensor, useDroppable, useSensors, useSensor, MeasuringStrategy } from '@dnd-kit/core';
import { SortableContext, useSortable, arrayMove, defaultAnimateLayoutChanges, horizontalListSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import multipleContainersCoordinateGetter from "../multipleContainersKeyboardCoordinates";
import { Item } from "./Item";
import { Container } from "./Container";
import classNames from 'classnames';
var defaultDropAnimationSideEffects = function defaultDropAnimationSideEffects(options) {
return function (_ref) {
var active = _ref.active,
dragOverlay = _ref.dragOverlay;
var originalStyles = {};
var styles = options.styles,
className = options.className;
if (styles !== null && styles !== void 0 && styles.active) {
for (var _i = 0, _Object$entries = Object.entries(styles.active); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
key = _Object$entries$_i[0],
value = _Object$entries$_i[1];
if (value === undefined) {
continue;
}
originalStyles[key] = active.node.style.getPropertyValue(key);
active.node.style.setProperty(key, value);
}
}
if (styles !== null && styles !== void 0 && styles.dragOverlay) {
for (var _i2 = 0, _Object$entries2 = Object.entries(styles.dragOverlay); _i2 < _Object$entries2.length; _i2++) {
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
_key = _Object$entries2$_i[0],
_value = _Object$entries2$_i[1];
if (_value === undefined) {
continue;
}
dragOverlay.node.style.setProperty(_key, _value);
}
}
if (className !== null && className !== void 0 && className.active) {
active.node.classList.add(className.active);
}
if (className !== null && className !== void 0 && className.dragOverlay) {
dragOverlay.node.classList.add(className.dragOverlay);
}
return function cleanup() {
for (var _i3 = 0, _Object$entries3 = Object.entries(originalStyles); _i3 < _Object$entries3.length; _i3++) {
var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2),
_key2 = _Object$entries3$_i[0],
_value2 = _Object$entries3$_i[1];
active.node.style.setProperty(_key2, _value2);
}
if (className !== null && className !== void 0 && className.active) {
active.node.classList.remove(className.active);
}
};
};
};
var animateLayoutChanges = function animateLayoutChanges(args) {
return defaultAnimateLayoutChanges(_objectSpread(_objectSpread({}, args), {}, {
wasDragging: true
}));
};
function DroppableContainer(_ref2) {
var _active$data$current;
var children = _ref2.children,
_ref2$columns = _ref2.columns,
columns = _ref2$columns === void 0 ? 1 : _ref2$columns,
disabled = _ref2.disabled,
id = _ref2.id,
items = _ref2.items,
style = _ref2.style,
props = _objectWithoutProperties(_ref2, _excluded);
var _useSortable = useSortable({
id: id,
data: {
type: 'container',
children: items
},
animateLayoutChanges: animateLayoutChanges
}),
active = _useSortable.active,
attributes = _useSortable.attributes,
isDragging = _useSortable.isDragging,
listeners = _useSortable.listeners,
over = _useSortable.over,
setNodeRef = _useSortable.setNodeRef,
transition = _useSortable.transition,
transform = _useSortable.transform;
var isOverContainer = over ? id === over.id && (active === null || active === void 0 ? void 0 : (_active$data$current = active.data.current) === null || _active$data$current === void 0 ? void 0 : _active$data$current.type) !== 'container' || items.includes(over.id) : false;
return /*#__PURE__*/React.createElement(Container, _extends({
ref: disabled ? undefined : setNodeRef,
style: _objectSpread(_objectSpread({}, style), {}, {
transition: transition,
transform: CSS.Translate.toString(transform),
opacity: isDragging ? 0.5 : undefined
}),
hover: isOverContainer,
handleProps: _objectSpread(_objectSpread({}, attributes), listeners),
columns: columns
}, props), children);
}
var dropAnimation = {
sideEffects: defaultDropAnimationSideEffects({
styles: {
active: {
opacity: '0.5'
}
}
})
};
export var TRASH_ID = 'void';
// const PLACEHOLDER_ID = 'placeholder';
// const empty: UniqueIdentifier[] = [];
export default function DndContainer(_ref3) {
var _ref3$adjustScale = _ref3.adjustScale,
adjustScale = _ref3$adjustScale === void 0 ? false : _ref3$adjustScale,
_ref3$itemCount = _ref3.itemCount,
itemCount = _ref3$itemCount === void 0 ? 3 : _ref3$itemCount,
cancelDrop = _ref3.cancelDrop,
columns = _ref3.columns,
_ref3$handle = _ref3.handle,
handle = _ref3$handle === void 0 ? false : _ref3$handle,
initialItems = _ref3.items,
containerStyle = _ref3.containerStyle,
_ref3$coordinateGette = _ref3.coordinateGetter,
coordinateGetter = _ref3$coordinateGette === void 0 ? multipleContainersCoordinateGetter : _ref3$coordinateGette,
_ref3$getItemStyles = _ref3.getItemStyles,
getItemStyles = _ref3$getItemStyles === void 0 ? function () {
return {};
} : _ref3$getItemStyles,
_ref3$wrapperStyle = _ref3.wrapperStyle,
wrapperStyle = _ref3$wrapperStyle === void 0 ? function () {
return {};
} : _ref3$wrapperStyle,
modifiers = _ref3.modifiers,
renderItem = _ref3.renderItem,
_ref3$trashable = _ref3.trashable,
trashable = _ref3$trashable === void 0 ? false : _ref3$trashable,
scrollable = _ref3.scrollable,
children = _ref3.children,
_ref3$updateItems = _ref3.updateItems,
updateItems = _ref3$updateItems === void 0 ? function () {
return {};
} : _ref3$updateItems,
_ref3$rowGroupTitle = _ref3.rowGroupTitle,
rowGroupTitle = _ref3$rowGroupTitle === void 0 ? '行分组' : _ref3$rowGroupTitle,
_ref3$colGroupTitle = _ref3.colGroupTitle,
colGroupTitle = _ref3$colGroupTitle === void 0 ? '列分组' : _ref3$colGroupTitle,
_ref3$filterColumns = _ref3.filterColumns,
filterColumns = _ref3$filterColumns === void 0 ? [] : _ref3$filterColumns;
var _useState = useState(function () {
return initialItems;
}),
_useState2 = _slicedToArray(_useState, 2),
items = _useState2[0],
setItems = _useState2[1];
useEffect(function () {
setItems(initialItems);
}, [initialItems]);
var _useState3 = useState(Object.keys(items)),
_useState4 = _slicedToArray(_useState3, 2),
containers = _useState4[0],
setContainers = _useState4[1];
var _useState5 = useState(null),
_useState6 = _slicedToArray(_useState5, 2),
activeId = _useState6[0],
setActiveId = _useState6[1];
var lastOverId = useRef(null);
// 是否移动到新容器
var recentlyMovedToNewContainer = useRef(false);
var isSortingContainer = activeId ? containers.includes(activeId) : false;
// 执行顺序: onDragStart,collisionDetection,onDragOver,[...collisionDetection],onDragEnd
/**
* Custom collision detection strategy optimized for multiple containers
* 针对多个容器优化的自定义碰撞检测策略
* - First, find any droppable containers intersecting with the pointer.
* - If there are none, find intersecting containers with the active draggable.
* - If there are no intersecting containers, return the last matched intersection
* 1.首先,找到与指针相交的任何可放置容器。2.如果没有,则查找具有活动可拖动对象的相交容器。3.如果没有交叉容器,则返回最后匹配的交叉
*/
var collisionDetectionStrategy = useCallback(function (args) {
if (activeId && activeId in items) {
return closestCenter(_objectSpread(_objectSpread({}, args), {}, {
droppableContainers: args.droppableContainers.filter(function (container) {
return container.id in items;
})
}));
}
// Start by finding any intersecting droppable
var pointerIntersections = pointerWithin(args);
var intersections = pointerIntersections.length > 0 ?
// If there are droppables intersecting with the pointer, return those
pointerIntersections : rectIntersection(args);
var overId = getFirstCollision(intersections, 'id');
if (overId != null) {
if (overId === TRASH_ID) {
// If the intersecting droppable is the trash, return early
// Remove this if you're not using trashable functionality in your app
return intersections;
}
if (overId in items) {
var containerItems = items[overId];
// If a container is matched and it contains items (columns 'A', 'B', 'C')
if (containerItems.length > 0) {
var _closestCenter$;
// 返回该容器中最近的滴管
// Return the closest droppable within that container
overId = (_closestCenter$ = closestCenter(_objectSpread(_objectSpread({}, args), {}, {
droppableContainers: args.droppableContainers.filter(function (container) {
return container.id !== overId && containerItems.includes(container.id);
})
}))[0]) === null || _closestCenter$ === void 0 ? void 0 : _closestCenter$.id;
}
}
lastOverId.current = overId;
return [{
id: overId
}];
}
// When a draggable item moves to a new container, the layout may shift
// and the `overId` may become `null`. We manually set the cached `lastOverId`
// to the id of the draggable item that was moved to the new container, otherwise
// the previous `overId` will be returned which can cause items to incorrectly shift positions
if (recentlyMovedToNewContainer.current) {
lastOverId.current = activeId;
}
// If no droppable is matched, return the last match
return lastOverId.current ? [{
id: lastOverId.current
}] : [];
}, [activeId, items]);
var _useState7 = useState(null),
_useState8 = _slicedToArray(_useState7, 2),
clonedItems = _useState8[0],
setClonedItems = _useState8[1];
// 传感器
var sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor), useSensor(KeyboardSensor, {
coordinateGetter: coordinateGetter
}));
var findContainer = function findContainer(id) {
if (id in items) {
return id;
}
return Object.keys(items).find(function (key) {
return items[key].includes(id);
});
};
var getIndex = function getIndex(id) {
var container = findContainer(id);
if (!container) {
return -1;
}
var index = items[container].indexOf(id);
return index;
};
var onDragCancel = function onDragCancel() {
if (clonedItems) {
// Reset items to their original state in case items have been
// Dragged across containers
setItems(clonedItems);
}
setActiveId(null);
setClonedItems(null);
};
useEffect(function () {
var id = requestAnimationFrame(function () {
recentlyMovedToNewContainer.current = false;
});
return function () {
return cancelAnimationFrame(id);
};
}, [items]);
var isOk = function isOk(active, over) {
var _items$row, _items$col;
var item = filterColumns.find(function (item) {
return item.title === active.id;
});
if (over.id === 'row' || items !== null && items !== void 0 && (_items$row = items.row) !== null && _items$row !== void 0 && _items$row.includes(over.id)) {
return item && item.rowGroup;
} else if (over.id === 'col' || items !== null && items !== void 0 && (_items$col = items.col) !== null && _items$col !== void 0 && _items$col.includes(over.id)) {
return item && item.colGroup;
}
return true;
};
var topContainers = containers.filter(function (item) {
return item !== 'tableHeader';
});
var tableContainer = containers.filter(function (item) {
return item === 'tableHeader';
})[0];
return /*#__PURE__*/React.createElement(DndContext, {
sensors: sensors,
collisionDetection: collisionDetectionStrategy,
measuring: {
droppable: {
strategy: MeasuringStrategy.Always
}
},
onDragStart: function onDragStart(_ref4) {
var active = _ref4.active;
setActiveId(active.id);
setClonedItems(items);
},
onDragOver: function onDragOver(_ref5) {
var active = _ref5.active,
over = _ref5.over;
var overId = over === null || over === void 0 ? void 0 : over.id;
if (overId == null || overId === TRASH_ID || active.id in items) {
return;
}
if (!isOk(active, over)) {
return;
}
var overContainer = findContainer(overId);
var activeContainer = findContainer(active.id);
if (!overContainer || !activeContainer) {
return;
}
if (activeContainer !== overContainer) {
setItems(function (items) {
var _objectSpread2;
var activeItems = items[activeContainer];
var overItems = items[overContainer];
var overIndex = overItems.indexOf(overId);
var activeIndex = activeItems.indexOf(active.id);
var newIndex;
if (overId in items) {
newIndex = overItems.length + 1;
} else {
// 当前激活的是否在目标下面
var isBelowOverItem = over && active.rect.current.translated && active.rect.current.translated.top > over.rect.top + over.rect.height;
var modifier = isBelowOverItem ? 1 : 0;
newIndex = overIndex >= 0 ? overIndex + modifier : overItems.length + 1;
}
recentlyMovedToNewContainer.current = true;
return _objectSpread(_objectSpread({}, items), {}, (_objectSpread2 = {}, _defineProperty(_objectSpread2, activeContainer, items[activeContainer].filter(function (item) {
return item !== active.id;
})), _defineProperty(_objectSpread2, overContainer, [].concat(_toConsumableArray(items[overContainer].slice(0, newIndex)), [items[activeContainer][activeIndex]], _toConsumableArray(items[overContainer].slice(newIndex, items[overContainer].length)))), _objectSpread2));
});
}
},
onDragEnd: function onDragEnd(_ref6) {
var active = _ref6.active,
over = _ref6.over;
// 容器拖拽
if (active.id in items && over !== null && over !== void 0 && over.id) {
setContainers(function (containers) {
var activeIndex = containers.indexOf(active.id);
var overIndex = containers.indexOf(over.id);
return arrayMove(containers, activeIndex, overIndex);
});
}
var activeContainer = findContainer(active.id);
if (!activeContainer) {
setActiveId(null);
return;
}
var overId = over === null || over === void 0 ? void 0 : over.id;
if (overId == null) {
setActiveId(null);
return;
}
if (overId === TRASH_ID) {
console.log('TRASH_ID', overId);
setItems(function (items) {
return _objectSpread(_objectSpread({}, items), {}, _defineProperty({}, activeContainer, items[activeContainer].filter(function (id) {
return id !== activeId;
})));
});
setActiveId(null);
return;
}
var overContainer = findContainer(overId);
if (overContainer) {
var activeIndex = items[activeContainer].indexOf(active.id);
var overIndex = items[overContainer].indexOf(overId);
if (activeIndex !== overIndex) {
var newItems = _objectSpread(_objectSpread({}, items), {}, _defineProperty({}, overContainer, arrayMove(items[overContainer], activeIndex, overIndex)));
// setItems(newItems);
updateItems(newItems);
} else {
updateItems(items);
}
}
setActiveId(null);
},
cancelDrop: cancelDrop,
onDragCancel: onDragCancel,
modifiers: modifiers
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex',
boxSizing: 'border-box'
}
}, topContainers.map(function (containerId) {
return /*#__PURE__*/React.createElement(DroppableContainer, {
key: containerId,
id: containerId,
label: containerId === 'row' ? rowGroupTitle : colGroupTitle,
columns: columns,
items: items[containerId],
scrollable: true,
style: containerStyle,
unstyled: false
}, /*#__PURE__*/React.createElement(SortableContext, {
items: items[containerId],
strategy: horizontalListSortingStrategy
}, items[containerId].map(function (value, index) {
return /*#__PURE__*/React.createElement(SortableItem, {
disabled: isSortingContainer,
key: value,
id: value,
index: index,
handle: true,
style: getItemStyles,
wrapperStyle: wrapperStyle,
renderItem: renderItem,
containerId: containerId,
getIndex: getIndex,
onRemove: function onRemove() {
updateItems(items, value);
}
});
})));
})), /*#__PURE__*/React.createElement("div", {
className: classNames('dnd_table_container'),
style: {
display: 'flex',
boxSizing: 'border-box',
justifyContent: 'column'
}
}, /*#__PURE__*/React.createElement(DroppableContainer, {
key: tableContainer,
id: tableContainer,
columns: 1,
items: items[tableContainer],
scrollable: scrollable,
style: containerStyle,
unstyled: false,
ulClassName: 'ulClassName',
isNoneBorder: true
}, /*#__PURE__*/React.createElement(SortableContext, {
items: items[tableContainer],
strategy: horizontalListSortingStrategy
}, /*#__PURE__*/React.createElement("li", {
style: {
width: '100%'
}
}, children)))), /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(DragOverlay, {
adjustScale: adjustScale,
dropAnimation: dropAnimation
}, activeId ? containers.includes(activeId) ? renderContainerDragOverlay(activeId) : renderSortableItemDragOverlay(activeId) : null), document.body), trashable && activeId && !containers.includes(activeId) ? /*#__PURE__*/React.createElement(Trash, {
id: TRASH_ID
}) : null);
function renderSortableItemDragOverlay(id) {
return /*#__PURE__*/React.createElement(Item, {
value: id,
handle: handle,
style: getItemStyles({
containerId: findContainer(id),
overIndex: -1,
index: getIndex(id),
value: id,
isSorting: true,
isDragging: true,
isDragOverlay: true
}),
color: getColor(id),
wrapperStyle: wrapperStyle({
index: 0
}),
renderItem: renderItem,
dragOverlay: true
});
}
function renderContainerDragOverlay(containerId) {
return /*#__PURE__*/React.createElement(Container, {
label: "Column ".concat(containerId),
columns: columns,
style: {
height: '100%'
},
shadow: true,
unstyled: false
}, items[containerId].map(function (item, index) {
return /*#__PURE__*/React.createElement(Item, {
key: item,
value: item,
handle: handle,
style: getItemStyles({
containerId: containerId,
overIndex: -1,
index: getIndex(item),
value: item,
isDragging: false,
isSorting: false,
isDragOverlay: false
}),
color: getColor(item),
wrapperStyle: wrapperStyle({
index: index
}),
renderItem: renderItem
});
}));
}
// function getNextContainerId() {
// const containerIds = Object.keys(items);
// const lastContainerId = containerIds[containerIds.length - 1];
// return String.fromCharCode(lastContainerId.charCodeAt(0) + 1);
// }
}
function getColor(id) {
switch (String(id)[0]) {
case 'A':
return '#7193f1';
case 'B':
return '#ffda6c';
case 'C':
return '#00bcd4';
case 'D':
return '#ef769f';
}
return undefined;
}
function Trash(_ref7) {
var id = _ref7.id;
var _useDroppable = useDroppable({
id: id
}),
setNodeRef = _useDroppable.setNodeRef,
isOver = _useDroppable.isOver;
return /*#__PURE__*/React.createElement("div", {
ref: setNodeRef,
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'fixed',
left: '50%',
marginLeft: -150,
bottom: 20,
width: 300,
height: 60,
borderRadius: 5,
border: '1px solid',
borderColor: isOver ? 'red' : '#DDD'
}
}, "Drop here to delete");
}
function SortableItem(_ref8) {
var disabled = _ref8.disabled,
id = _ref8.id,
index = _ref8.index,
handle = _ref8.handle,
renderItem = _ref8.renderItem,
style = _ref8.style,
containerId = _ref8.containerId,
getIndex = _ref8.getIndex,
wrapperStyle = _ref8.wrapperStyle,
onRemove = _ref8.onRemove;
var _useSortable2 = useSortable({
id: id
}),
setNodeRef = _useSortable2.setNodeRef,
listeners = _useSortable2.listeners,
isDragging = _useSortable2.isDragging,
isSorting = _useSortable2.isSorting,
over = _useSortable2.over,
overIndex = _useSortable2.overIndex,
transform = _useSortable2.transform,
transition = _useSortable2.transition;
var mounted = useMountStatus();
var mountedWhileDragging = isDragging && !mounted;
return /*#__PURE__*/React.createElement(Item, {
ref: disabled ? undefined : setNodeRef,
value: id,
dragging: isDragging,
sorting: isSorting,
handle: handle,
handleProps: undefined,
index: index,
wrapperStyle: wrapperStyle({
index: index
}),
style: style({
index: index,
value: id,
isDragging: isDragging,
isSorting: isSorting,
overIndex: over ? getIndex(over.id) : overIndex,
containerId: containerId
}),
color: getColor(id),
transition: transition,
transform: transform,
fadeIn: mountedWhileDragging,
listeners: listeners,
renderItem: renderItem,
onRemove: onRemove
});
}
function useMountStatus() {
var _useState9 = useState(false),
_useState10 = _slicedToArray(_useState9, 2),
isMounted = _useState10[0],
setIsMounted = _useState10[1];
useEffect(function () {
var timeout = setTimeout(function () {
return setIsMounted(true);
}, 500);
return function () {
return clearTimeout(timeout);
};
}, []);
return isMounted;
}