feat: improve dnd
This commit is contained in:
parent
8a2ab9f86b
commit
3b5f43ea09
@ -1,19 +1,11 @@
|
||||
import { useDroppable } from '@dnd-kit/core';
|
||||
import { useDndMonitor, useDroppable } from '@dnd-kit/core';
|
||||
import { css } from '@emotion/css';
|
||||
import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import cls from 'classnames';
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { DndContext } from '../../common/dnd-context';
|
||||
|
||||
export const Grid: any = observer((props) => {
|
||||
return (
|
||||
<div>
|
||||
<DndContext>{props.children}</DndContext>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const ColDivider = (props) => {
|
||||
const { isOver, setNodeRef } = useDroppable({
|
||||
id: props.id,
|
||||
@ -27,6 +19,88 @@ const ColDivider = (props) => {
|
||||
return <div ref={setNodeRef} style={{ width: 24, ...droppableStyle }}></div>;
|
||||
};
|
||||
|
||||
const RowDivider = (props) => {
|
||||
const { isOver, setNodeRef } = useDroppable({
|
||||
id: props.id,
|
||||
data: props.data,
|
||||
});
|
||||
|
||||
const droppableStyle = {};
|
||||
|
||||
if (isOver) {
|
||||
droppableStyle['backgroundColor'] = 'green';
|
||||
}
|
||||
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
useDndMonitor({
|
||||
onDragStart(event) {
|
||||
setActive(true);
|
||||
},
|
||||
onDragMove(event) {},
|
||||
onDragOver(event) {},
|
||||
onDragEnd(event) {
|
||||
setActive(false);
|
||||
},
|
||||
onDragCancel(event) {
|
||||
setActive(false);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
style={{
|
||||
zIndex: active ? 1000 : 0,
|
||||
height: 24,
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
marginTop: -24,
|
||||
...droppableStyle,
|
||||
}}
|
||||
></div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Grid: any = observer((props) => {
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const addr = field.address.toString();
|
||||
const wrapSchema = (schema: Schema) => {
|
||||
const row = new Schema({
|
||||
type: 'void',
|
||||
name: `row_${uid()}`,
|
||||
'x-uid': uid(),
|
||||
'x-component': 'Grid.Row',
|
||||
});
|
||||
const col = row.addProperty(uid(), {
|
||||
type: 'void',
|
||||
'x-uid': uid(),
|
||||
'x-component': 'Grid.Col',
|
||||
});
|
||||
if (Schema.isSchemaInstance(schema)) {
|
||||
schema.parent = col;
|
||||
}
|
||||
col.addProperty(schema.name, schema);
|
||||
return row;
|
||||
};
|
||||
return (
|
||||
<div className={'nb-grid'} style={{ position: 'relative' }}>
|
||||
<DndContext>
|
||||
<RowDivider id={`${addr}_0`} data={{ wrapSchema, insertAdjacent: 'afterBegin', schema: fieldSchema }} />
|
||||
{fieldSchema.mapProperties((schema, key, index) => {
|
||||
return (
|
||||
<React.Fragment key={key}>
|
||||
<RecursionField name={key} schema={schema} />
|
||||
<RowDivider id={`${addr}_${index + 1}`} data={{ wrapSchema, insertAdjacent: 'afterEnd', schema }} />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</DndContext>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Grid.Row = observer((props) => {
|
||||
const field = useField();
|
||||
const fieldSchema = useFieldSchema();
|
||||
@ -58,6 +132,8 @@ Grid.Row = observer((props) => {
|
||||
css`
|
||||
margin: 0 -24px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
`,
|
||||
)}
|
||||
>
|
||||
@ -81,5 +157,17 @@ Grid.Row = observer((props) => {
|
||||
});
|
||||
|
||||
Grid.Col = observer((props) => {
|
||||
return <div className={cls('nb-grid-col')}>{props.children}</div>;
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
'nb-grid-col',
|
||||
css`
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
`,
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DndContext as DndKitContext, DragEndEvent } from '@dnd-kit/core';
|
||||
import { DndContext as DndKitContext, DragEndEvent, rectIntersection } from '@dnd-kit/core';
|
||||
import { observer } from '@formily/react';
|
||||
import React from 'react';
|
||||
import { createDesignable, useDesignable } from '../../hooks';
|
||||
@ -12,12 +12,15 @@ const useDragEnd = () => {
|
||||
const overSchema = over?.data?.current?.schema;
|
||||
const insertAdjacent = over?.data?.current?.insertAdjacent;
|
||||
const wrapSchema = over?.data?.current?.wrapSchema;
|
||||
const onInsertAdjacent = over?.data?.current?.onInsertAdjacent;
|
||||
|
||||
if (!activeSchema || !overSchema) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeSchema === overSchema) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dn = createDesignable({
|
||||
current: overSchema,
|
||||
});
|
||||
@ -30,21 +33,19 @@ const useDragEnd = () => {
|
||||
}
|
||||
|
||||
if (insertAdjacent) {
|
||||
console.log('removeIfChildrenEmpty', activeSchema);
|
||||
dn.insertAdjacent(insertAdjacent, activeSchema, {
|
||||
wrap: wrapSchema,
|
||||
removeEmptyParents: true,
|
||||
});
|
||||
// onInsertAdjacent && onInsertAdjacent({
|
||||
// dn,
|
||||
// orginDraggedParentSchema,
|
||||
// draggedSchema: activeSchema,
|
||||
// });
|
||||
return;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const DndContext = observer((props) => {
|
||||
return <DndKitContext onDragEnd={useDragEnd()}>{props.children}</DndKitContext>;
|
||||
return (
|
||||
<DndKitContext collisionDetection={rectIntersection} onDragEnd={useDragEnd()}>
|
||||
{props.children}
|
||||
</DndKitContext>
|
||||
);
|
||||
});
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './dnd-context';
|
||||
export * from './sortable-item';
|
||||
|
||||
|
@ -47,15 +47,40 @@ export const SortableItem = observer((props) => {
|
||||
});
|
||||
|
||||
export const DragHandler = () => {
|
||||
const { attributes, listeners, setNodeRef, transform } = useContext(DraggableContext);
|
||||
const { isDragging, attributes, listeners, setNodeRef, transform } = useContext(DraggableContext);
|
||||
const style = transform
|
||||
? {
|
||||
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={{ ...style, display: 'inline-block' }} {...listeners} {...attributes}>
|
||||
Drag
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: isDragging ? 'inline-block' : 'none', fontSize: 10, position: 'absolute', zIndex: 0 }}>
|
||||
Drag
|
||||
</div>
|
||||
<div
|
||||
ref={setNodeRef}
|
||||
style={{
|
||||
...style,
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
backgroundColor: '#333',
|
||||
lineHeight: 0,
|
||||
height: 2,
|
||||
width: 2,
|
||||
fontSize: 0,
|
||||
display: 'inline-block',
|
||||
}}
|
||||
{...listeners}
|
||||
{...attributes}
|
||||
>
|
||||
<div style={{ fontSize: 10 }}>Drag</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -86,11 +86,10 @@ export class Designable {
|
||||
}
|
||||
}
|
||||
|
||||
removeIfChildrenEmpty(schema?: Schema, options: { recursive?: boolean } = {}) {
|
||||
removeIfChildrenEmpty(schema?: Schema) {
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
const { recursive } = options;
|
||||
let s = schema;
|
||||
const count = Object.keys(s.properties || {}).length;
|
||||
console.log('removeIfChildrenEmpty', count, s.properties);
|
||||
@ -100,9 +99,6 @@ export class Designable {
|
||||
let removed;
|
||||
while (s.parent) {
|
||||
removed = s.parent.removeProperty(s.name);
|
||||
if (!recursive) {
|
||||
break;
|
||||
}
|
||||
const count = Object.keys(s.parent.properties || {}).length;
|
||||
if (count > 0) {
|
||||
break;
|
||||
@ -254,6 +250,7 @@ export class Designable {
|
||||
const { wrap = defaultWrap, removeEmptyParents } = options;
|
||||
if (Schema.isSchemaInstance(schema)) {
|
||||
schema.parent.removeProperty(schema.name);
|
||||
console.log('insertAfterEnd', removeEmptyParents)
|
||||
if (removeEmptyParents) {
|
||||
this.removeIfChildrenEmpty(schema.parent);
|
||||
}
|
||||
@ -327,8 +324,8 @@ export function useDesignable() {
|
||||
remove() {
|
||||
dn.remove();
|
||||
},
|
||||
insertAdjacent(position: Position, schema: ISchema) {
|
||||
dn.insertAdjacent(position, schema);
|
||||
insertAdjacent(position: Position, schema: ISchema, options: InsertAdjacentOptions = {}) {
|
||||
dn.insertAdjacent(position, schema, options);
|
||||
},
|
||||
insertBeforeBegin(schema: ISchema) {
|
||||
dn.insertBeforeBegin(schema);
|
||||
|
Loading…
Reference in New Issue
Block a user