From 88ce573bf85af2dcfc6c6b1db36fd0bf6332b934 Mon Sep 17 00:00:00 2001 From: soulwu Date: Thu, 16 Jan 2020 00:39:47 +0800 Subject: [PATCH] feat: use react-drag-listview instead of ReactDnD and support antd draggable table (#609) --- docs/Examples/antd/List.md | 63 ++++++ packages/antd/src/fields/table.tsx | 52 ++++- packages/next/package.json | 2 - packages/next/src/fields/table.tsx | 213 ++++++------------ packages/next/src/types.ts | 29 +-- packages/react-shared-components/package.json | 3 +- .../src/DragListView.tsx | 18 ++ packages/react-shared-components/src/index.ts | 1 + packages/react-shared-components/src/types.ts | 7 + 9 files changed, 202 insertions(+), 186 deletions(-) create mode 100644 packages/react-shared-components/src/DragListView.tsx diff --git a/docs/Examples/antd/List.md b/docs/Examples/antd/List.md index 0fbeb325358..b18d484114d 100644 --- a/docs/Examples/antd/List.md +++ b/docs/Examples/antd/List.md @@ -187,6 +187,69 @@ const App = () => ( ReactDOM.render(, document.getElementById('root')) ``` +# Dragable Table Style + +> 数组场景,列表型数组,使用拖拽排序,对于需要做数据对比分析的场景,比较适合,但是它对数据结构 +> 的要求,必须是 ObjectList + +#### Demo 示例 + +```jsx +import React from 'react' +import ReactDOM from 'react-dom' +import { + SchemaForm, + SchemaMarkupField as Field, + FormButtonGroup, + Submit, + Reset, + FormItemGrid, + FormCard, + FormPath, + FormBlock, + FormLayout, + createFormActions +} from '@uform/antd' +import { Button } from 'antd' +import Printer from '@uform/printer' +import 'antd/dist/antd.css' + +const App = () => ( + + + {}, + renderMoveDown: () => {}, + operationsWidth: 100 + }} + > + + + + + + + + +) +ReactDOM.render(, document.getElementById('root')) +``` + # Card Style > 数组场景,卡片数组,信息层级结构更加清晰的要求,必须是 ObjectList diff --git a/packages/antd/src/fields/table.tsx b/packages/antd/src/fields/table.tsx index 1633d2b87cb..e33ea7ad517 100644 --- a/packages/antd/src/fields/table.tsx +++ b/packages/antd/src/fields/table.tsx @@ -6,7 +6,7 @@ import { Schema } from '@uform/react-schema-renderer' import { toArr, isFn, isArr, FormPath } from '@uform/shared' -import { ArrayList } from '@uform/react-shared-components' +import { ArrayList, DragListView } from '@uform/react-shared-components' import { CircleButton, TextButton } from '../components/Button' import { Table, Form, Icon } from 'antd' import { CompatAntdFormItemProps } from '../compat/FormItem' @@ -21,6 +21,17 @@ const ArrayComponents = { MoveUpIcon: () => } +const DragHandler = styled.span` + width: 7px; + display: inline-block; + height: 14px; + border: 2px dotted #c5c5c5; + border-top: 0; + border-bottom: 0; + cursor: move; + margin-bottom: 24px; +` + const FormTableField = styled( (props: ISchemaFieldComponentProps & { className: string }) => { const { value, schema, className, editable, path, mutators } = props @@ -32,6 +43,7 @@ const FormTableField = styled( renderEmpty, renderExtraOperations, operations, + dragable, ...componentProps } = schema.getExtendsComponentProps() || {} const onAdd = () => { @@ -40,6 +52,9 @@ const FormTableField = styled( : schema.items mutators.push(items.getEmptyValue()) } + const onMove = (dragIndex, dropIndex) => { + mutators.move(dragIndex, dropIndex) + } const renderColumns = (items: Schema) => { return items.mapProperties((props, key) => { const itemProps = { @@ -100,6 +115,24 @@ const FormTableField = styled( } }) } + if (dragable) { + columns.unshift({ + width: 20, + render: () => { + return + } + }) + } + const renderTable = () => { + return ( +
+ ) + } return (
-
+ {dragable ? ( + + {renderTable()} + + ) : ( + renderTable() + )} {({ children }) => { return ( diff --git a/packages/next/package.json b/packages/next/package.json index 29dd8ee24b3..f39d132b453 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -31,8 +31,6 @@ "@uform/react-shared-components": "^1.0.0-rc.3", "@uform/shared": "^1.0.0-rc.3", "classnames": "^2.2.6", - "react-dnd": "^10.0.2", - "react-dnd-html5-backend": "^10.0.2", "react-eva": "^1.0.0-alpha.0", "react-stikky": "^0.1.15", "rxjs": "^6.5.1", diff --git a/packages/next/src/fields/table.tsx b/packages/next/src/fields/table.tsx index dd04396d98b..40160a3608f 100644 --- a/packages/next/src/fields/table.tsx +++ b/packages/next/src/fields/table.tsx @@ -6,20 +6,15 @@ import { Schema } from '@uform/react-schema-renderer' import { toArr, isFn, isArr, FormPath } from '@uform/shared' -import { ArrayList } from '@uform/react-shared-components' +import { ArrayList, DragListView } from '@uform/react-shared-components' import { CircleButton, TextButton } from '../components/Button' import { Table, Form, Icon } from '@alifd/next' import styled from 'styled-components' import { CompatNextFormItemProps } from '../compat/FormItem' import cls from 'classnames' -import { DndProvider, useDrag, useDrop } from 'react-dnd' -import HTML5Backend from 'react-dnd-html5-backend' import { - IDragableRowWrapperProps, IDragableRowProps, IDragableTableProps, - IDragObject, - ICollectedProps, IDragHandlerCellProps } from '../types' @@ -41,13 +36,10 @@ const ArrayComponents = { } const DragHandlerCell = styled( - ({ children, drag, ...props }: IDragHandlerCellProps) => { - const ref = useRef(null) - drag(ref) - + ({ children, ...props }: IDragHandlerCellProps) => { return (
- + {children}
) @@ -79,94 +71,14 @@ const DragHandlerCell = styled( } ` -const RowWrapper = styled( - ({ - children, - rowIndex, - moveRow, - preview, - ...props - }: IDragableRowWrapperProps) => { - const ref = useRef(null) - const [{ isOver, dragingIndex }, drop] = useDrop< - IDragObject, - any, - ICollectedProps - >({ - accept: 'row', - drop(item, monitor) { - const dragIndex = item.index - const dropIndex = rowIndex - if (dragIndex === dropIndex) { - return - } - moveRow(dragIndex, dropIndex) - item.index = dropIndex - }, - collect(monitor) { - const dragingItem = monitor.getItem() - - return { - isOver: monitor.isOver(), - dragingIndex: dragingItem ? dragingItem.index : -1 - } - } - }) - - drop(ref) - preview(ref) - - const child = React.Children.only(children) - - return React.cloneElement(child, { - ...child.props, - ref, - className: cls(child.props.className, props.className, { - 'drop-over-downward': isOver && rowIndex > dragingIndex, - 'drop-over-upward': isOver && rowIndex < dragingIndex - }) - }) - } -)` - &.drop-over-downward { - td { - border-bottom: 2px dashed #0070cc !important; - } - } - &.drop-over-upward { - td { - border-top: 2px dashed #0070cc !important; - } - } -` - const DragableRow = forwardRef( - ({ moveRow, columns, ...props }: IDragableRowProps, ref) => { - const [, drag, preview] = useDrag({ - item: { - type: 'row', - id: props.record[props.primaryKey], - index: props.rowIndex - } - }) - + ({ columns, ...props }: IDragableRowProps, ref) => { const [firstCol, ...otherCols] = columns - const createWrapper = row => { - return ( - - {row} - - ) - } - return ( {content} + return {content} } }, ...otherCols ]} - wrapper={createWrapper} /> ) } ) -const DragableTable = styled(({ onMoveRow, ...props }: IDragableTableProps) => { +const DragableTable = styled(props => { return ( - - ({ moveRow: onMoveRow })} - components={{ - Row: DragableRow - }} - /> - +
) })` &.next-table .next-table-header th:nth-child(1) .next-table-cell-wrapper { @@ -236,7 +145,7 @@ const FormTableField = styled( : schema.items mutators.push(items.getEmptyValue()) } - const onMoveRow = (dragIndex, dropIndex) => { + const onMove = (dragIndex, dropIndex) => { mutators.move(dragIndex, dropIndex) } const renderColumns = (items: Schema) => { @@ -267,6 +176,51 @@ const FormTableField = styled( ) }) } + const renderTable = () => { + return ( + + {isArr(schema.items) + ? schema.items.reduce((buf, items) => { + return buf.concat(renderColumns(items)) + }, []) + : renderColumns(schema.items)} + { + return ( + +
+ mutators.remove(index)} + /> + mutators.moveDown(index)} + /> + mutators.moveUp(index)} + /> + {isFn(renderExtraOperations) + ? renderExtraOperations(index) + : renderExtraOperations} +
+
+ ) + }} + /> +
+ ) + } return (
- - {isArr(schema.items) - ? schema.items.reduce((buf, items) => { - return buf.concat(renderColumns(items)) - }, []) - : renderColumns(schema.items)} - { - return ( - -
- mutators.remove(index)} - /> - mutators.moveDown(index)} - /> - mutators.moveUp(index)} - /> - {isFn(renderExtraOperations) - ? renderExtraOperations(index) - : renderExtraOperations} -
-
- ) - }} - /> -
+ {dragable ? ( + {renderTable()} + ) : ( + renderTable() + )} {({ children }) => { return ( diff --git a/packages/next/src/types.ts b/packages/next/src/types.ts index 3964742eb0e..76af12b9850 100644 --- a/packages/next/src/types.ts +++ b/packages/next/src/types.ts @@ -106,35 +106,8 @@ export interface IFormStep extends StepProps { dataSource: Array } -export interface IDragObject extends DragObjectWithType { - id: T - index: number -} - -export interface ICollectedProps { - isOver: boolean - dragingIndex: number -} - -export type onMoveRowCallback = (dragIndex: number, dropIndex: number) => void - -export type IDragHandlerCellProps = React.PropsWithChildren<{ - drag: ConnectDragSource -}> - -export type IDragableRowWrapperProps = React.PropsWithChildren<{ - rowIndex: number - moveRow: onMoveRowCallback - preview: ConnectDragPreview -}> +export type IDragHandlerCellProps = React.PropsWithChildren<{}> export interface IDragableRowProps { - rowIndex: number - moveRow: onMoveRowCallback columns: ColumnProps[] - record: { [key: string]: any } -} - -export interface IDragableTableProps extends TableProps { - onMoveRow: onMoveRowCallback } diff --git a/packages/react-shared-components/package.json b/packages/react-shared-components/package.json index 031011846de..ee6adb2ca31 100644 --- a/packages/react-shared-components/package.json +++ b/packages/react-shared-components/package.json @@ -26,6 +26,7 @@ "typescript": "^3.5.2" }, "dependencies": { - "@uform/shared": "^1.0.0-rc.3" + "@uform/shared": "^1.0.0-rc.3", + "react-drag-listview": "^0.1.6" } } diff --git a/packages/react-shared-components/src/DragListView.tsx b/packages/react-shared-components/src/DragListView.tsx new file mode 100644 index 00000000000..1ceef63e05a --- /dev/null +++ b/packages/react-shared-components/src/DragListView.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import ReactDragListView from 'react-drag-listview' +import { IDragListViewProps } from './types' + +export const DragListView: React.FC = ({ + children, + ...props +}) => { + return ( + + {children} + + ) +} diff --git a/packages/react-shared-components/src/index.ts b/packages/react-shared-components/src/index.ts index c7a46558638..d85bf94f722 100644 --- a/packages/react-shared-components/src/index.ts +++ b/packages/react-shared-components/src/index.ts @@ -2,3 +2,4 @@ export * from './ArrayList' export * from './PreviewText' export * from './PasswordStrength' export * from './types' +export * from './DragListView' diff --git a/packages/react-shared-components/src/types.ts b/packages/react-shared-components/src/types.ts index 75e7e7b3517..a324cd50733 100644 --- a/packages/react-shared-components/src/types.ts +++ b/packages/react-shared-components/src/types.ts @@ -105,3 +105,10 @@ export type IArrayListEmptyProps = IArrayListAdditionProps export interface PreviewTextConfigProps { previewPlaceholder?: string | ((props: IPreviewTextProps) => string) } + +export interface IDragListViewProps { + onDragEnd: (fromIndex: number, toIndex: number) => void + handleSelector?: string + nodeSelector?: string + ignoreSelector?: string +}