import React, { createContext, useContext, forwardRef, useState } from 'react';
import { SortableContext, useSortable, horizontalListSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import cls from 'classnames';
import { DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core';
import { MenuOutlined } from '@ant-design/icons';
import { createPortal } from 'react-dom';
import { SortableItem } from '../../components/Sortable';
import { findPropertyByPath, getSchemaPath, useDesignable } from '../../components/schema-renderer';
import { updateSchema } from '..';
import { Schema } from '@formily/react';
import { isColumn } from './utils';
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;
}