import React, { forwardRef, useState } from 'react'; import { SortableContext, useSortable, horizontalListSortingStrategy, verticalListSortingStrategy, sortableKeyboardCoordinates, } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { Table } from 'antd'; import { createContext } from 'react'; import { useContext } from 'react'; import { range } from 'lodash'; import parse from 'html-react-parser'; import cls from 'classnames'; import { MenuOutlined } from '@ant-design/icons'; import { DndContext, DragOverlay, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, useDroppable, useDraggable, } from '@dnd-kit/core'; import { createPortal } from 'react-dom'; import { useRef } from 'react'; import { SortableItem } from '../../components/Sortable'; import { findPropertyByPath, getSchemaPath, useDesignable, } from '../../components/schema-renderer'; import { updateSchema } from '..'; import { Schema } from '@formily/react'; import { isColumn, isColumnComponent } from '.'; export const RowDraggableContext = createContext({}); export const ColDraggableContext = createContext(null); export const CellContext = createContext(null); export function SortableColumn(props) { const { className } = props; const { isOver, setNodeRef: setDroppableNodeRef } = useDroppable({ id: `droppable-${props['id']}`, }); const { isDragging, attributes, listeners, setNodeRef: setDraggableNodeRef, transform, } = useDraggable({ id: `draggable-${props['id']}`, }); return (
{props.children} {/* Drag */}
); } export function SortableBodyRow(props: any) { const { className, style: prevStyle, ['data-row-key']: dataRowKey, ...others } = props; const { isDragging, attributes, listeners, setNodeRef, setDraggableNodeRef, overIndex, transform, transition, } = useSortable({ id: dataRowKey }); const style = { ...prevStyle, transform: CSS.Transform.toString(transform), transition, }; return ( { return `td${child.key}`; })} > {React.Children.map(props.children, (child, index) => ( {child} ))} ); } export function SortableHeaderRow(props) { const { root, remove, insertAfter } = useDesignable(); const moveToAfter = (path1, path2) => { if (!path1 || !path2) { return; } if (path1.join('.') === path2.join('.')) { return; } const data = findPropertyByPath(root, path1); if (!data) { return; } remove(path1); return insertAfter(data.toJSON(), path2); }; const [dragOverlayContent, setDragOverlayContent] = useState(''); return ( { const previewRef = event.active.data?.current?.previewRef as { current: HTMLElement; }; if (previewRef?.current) { setDragOverlayContent(previewRef.current.textContent || ''); } }} onDragEnd={async (event) => { const path1 = event.active?.data?.current?.path; const path2 = event.over?.data?.current?.path; const data = moveToAfter(path1, path2); await updateSchema(data); }} > {createPortal( {dragOverlayContent} , document.body, )} {React.Children.map(props.children, (child, index) => ( {child} ))} ); } export function SortableHeaderCell(props) { const id = useContext(CellContext); if (['RC_TABLE_KEY', 'addnew', 'operation'].includes(id)) { return ; } const { schema } = useDesignable(); const columns: Schema[] = schema.reduceProperties((columns, current) => { if (!isColumn(current)) { return [...columns]; } if (current.name === id) { return [...columns, current]; } return [...columns]; }, []); const column = columns.shift(); if (!column) { return ; } return ( ((props, ref) => ( ))} /> ); } export function SortableBodyCell(props) { const id = useContext(CellContext); const { isDragging, attributes, listeners, setNodeRef, setDraggableNodeRef, setDroppableNodeRef, transform, transition, } = useSortable({ id: id }); const style = { ...props.style, transform: CSS.Transform.toString(transform), transition, }; return (
Drag
{props.children} ); } export function SortableRowHandle(props) { const { className, ...others } = props; const { setDraggableNodeRef, attributes, listeners } = useContext(RowDraggableContext); return setDraggableNodeRef ? ( ) : null; }