UNPKG

linkmore-design

Version:

🌈 🚀lm组件库。🚀

637 lines (629 loc) 23.6 kB
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; }