improve code
This commit is contained in:
parent
8b34b84a5e
commit
699726d5bb
@ -20,7 +20,7 @@ import { observable } from '@formily/reactive';
|
||||
import { uid, clone } from '@formily/shared';
|
||||
import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd';
|
||||
|
||||
import { Space, Card } from 'antd';
|
||||
import { Space, Card, Modal } from 'antd';
|
||||
import { Action, useLogin, useRegister, useSubmit } from '../action';
|
||||
import { AddNew } from '../add-new';
|
||||
import { Cascader } from '../cascader';
|
||||
@ -46,6 +46,9 @@ import { TimePicker } from '../time-picker';
|
||||
import { Upload } from '../upload';
|
||||
import { FormItem } from '../form-item';
|
||||
|
||||
import { CodeOutlined } from '@ant-design/icons';
|
||||
import Editor from '@monaco-editor/react';
|
||||
|
||||
export const BlockContext = createContext({ dragRef: null });
|
||||
|
||||
const Div = (props) => <div {...props} />;
|
||||
@ -170,6 +173,30 @@ export function useDesignable(path?: any) {
|
||||
return {
|
||||
schema: currentSchema,
|
||||
refresh,
|
||||
prepend: (property: ISchema, targetPath?: any): Schema => {
|
||||
let target = currentSchema;
|
||||
if (targetPath) {
|
||||
target = findPropertyByPath(schema, targetPath);
|
||||
}
|
||||
if (!target) {
|
||||
console.error('target schema does not exist.');
|
||||
return;
|
||||
}
|
||||
if (!property.name) {
|
||||
property.name = uid();
|
||||
}
|
||||
const properties = {};
|
||||
properties[property.name] = property;
|
||||
Object.keys(target.properties).forEach((name, index) => {
|
||||
const current = target.properties[name];
|
||||
current.parent.removeProperty(current.name);
|
||||
properties[current.name] = current.toJSON();
|
||||
});
|
||||
console.log({ properties }, target.properties)
|
||||
target.setProperties(properties);
|
||||
refresh();
|
||||
return target.properties[property.name];
|
||||
},
|
||||
appendChild: (property: ISchema, targetPath?: any): Schema => {
|
||||
let target = currentSchema;
|
||||
if (targetPath) {
|
||||
@ -222,6 +249,27 @@ export function useDesignable(path?: any) {
|
||||
refresh();
|
||||
return target.parent.properties[property.name];
|
||||
},
|
||||
deepRemove(targetPath?: any) {
|
||||
let target = currentSchema;
|
||||
if (targetPath) {
|
||||
target = findPropertyByPath(schema, targetPath);
|
||||
}
|
||||
if (!target) {
|
||||
console.error('target schema does not exist.');
|
||||
return;
|
||||
}
|
||||
const remove = (s: Schema) => {
|
||||
if (!s.parent) {
|
||||
return;
|
||||
}
|
||||
s.parent.removeProperty(s.name);
|
||||
if (Object.keys(s.parent.properties || {}).length === 0) {
|
||||
remove(s.parent);
|
||||
}
|
||||
};
|
||||
remove(target);
|
||||
refresh();
|
||||
},
|
||||
remove(targetPath?: any) {
|
||||
let target = currentSchema;
|
||||
if (targetPath) {
|
||||
@ -274,6 +322,7 @@ export const createDesignableSchemaField = (options) => {
|
||||
}}
|
||||
>
|
||||
<SchemaField schema={schema} />
|
||||
<CodePreview schema={schema} />
|
||||
</DesignableContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -281,6 +330,23 @@ export const createDesignableSchemaField = (options) => {
|
||||
return DesignableSchemaField;
|
||||
};
|
||||
|
||||
const CodePreview = ({ schema }) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<CodeOutlined onClick={() => setVisible(true)} />
|
||||
<Modal width={'80%'} onCancel={() => setVisible(false)} visible={visible}>
|
||||
<Editor
|
||||
height="60vh"
|
||||
defaultLanguage="json"
|
||||
value={JSON.stringify(schema.toJSON(), null, 2)}
|
||||
/>
|
||||
{/* <pre>{JSON.stringify(schema.toJSON(), null, 2)}</pre> */}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const DesignableSchemaField = createDesignableSchemaField({
|
||||
scope,
|
||||
components,
|
||||
|
@ -13,82 +13,205 @@ import { FormItem } from '../../form-item';
|
||||
import { createDesignableSchemaField } from '../../DesignableSchemaField';
|
||||
import { createForm } from '@formily/core';
|
||||
import { Grid } from '../';
|
||||
import { Card } from 'antd';
|
||||
|
||||
const schema: ISchema = {
|
||||
type: 'object',
|
||||
type: 'void',
|
||||
name: uid(),
|
||||
'x-component': 'Grid',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`row_${uid()}`]: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-component-props': {
|
||||
width: 30,
|
||||
},
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
"x-component-props": {
|
||||
width: 30,
|
||||
},
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
"x-component-props": {
|
||||
width: 70,
|
||||
},
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`row_${uid()}`]: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-component-props': {
|
||||
width: 70,
|
||||
},
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
name: uid(),
|
||||
'x-decorator': 'Card',
|
||||
'x-component': 'Grid',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-component-props': {
|
||||
width: 30,
|
||||
},
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
'x-component-props': {
|
||||
width: 70,
|
||||
},
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`row_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[`col_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[`block_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Block',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'string',
|
||||
title: uid(),
|
||||
'x-designable-bar': 'FormItem.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -106,6 +229,7 @@ const DesignableSchemaField = createDesignableSchemaField({
|
||||
Grid,
|
||||
Input,
|
||||
FormItem,
|
||||
Card,
|
||||
},
|
||||
});
|
||||
|
||||
@ -114,7 +238,12 @@ const form = createForm();
|
||||
export default () => {
|
||||
return (
|
||||
<FormProvider form={form}>
|
||||
<DesignableSchemaField schema={schema} />
|
||||
<DesignableSchemaField schema={{
|
||||
type: 'object',
|
||||
properties: {
|
||||
[schema.name]: schema,
|
||||
}
|
||||
}} />
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
@ -2,30 +2,35 @@ import React, { createContext, useContext, useEffect, useRef } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useMouseEvents, useWillUnmount } from 'beautiful-react-hooks';
|
||||
import { useField } from '@formily/react';
|
||||
import { useMount } from 'ahooks';
|
||||
import constate from 'constate';
|
||||
|
||||
export const DragDropManagerContext = createContext<any>({
|
||||
drag: null,
|
||||
drops: {},
|
||||
name: `${Math.random()}`,
|
||||
});
|
||||
|
||||
export function DragDropProvider(props) {
|
||||
const { gridRef, onDrop, children } = props;
|
||||
return (
|
||||
<DragDropManagerContext.Provider
|
||||
value={{
|
||||
drag: null,
|
||||
drops: {},
|
||||
onDrop,
|
||||
gridRef,
|
||||
name: `${Math.random()}`,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</DragDropManagerContext.Provider>
|
||||
);
|
||||
export function useDragDropManager() {
|
||||
const [drag, setDrag] = useState(null);
|
||||
const [drop, setDrop] = useState(null);
|
||||
const [drops, setDrops] = useState({});
|
||||
const addDrop = (dropId, data) =>
|
||||
setDrops((prevDrops) => {
|
||||
prevDrops[dropId] = data;
|
||||
return prevDrops;
|
||||
});
|
||||
const getDrop = (dropId) => {
|
||||
return drops[dropId];
|
||||
};
|
||||
return { drag, drop, drops, setDrag, addDrop, setDrop, getDrop };
|
||||
}
|
||||
|
||||
const [DragDropManagerProvider, useDragDropManagerContext] =
|
||||
constate(useDragDropManager);
|
||||
|
||||
export { DragDropManagerProvider, useDragDropManagerContext };
|
||||
|
||||
// export const DragDropManagerContext = createContext<any>({
|
||||
// drag: null,
|
||||
// drops: {},
|
||||
// name: `${Math.random()}`,
|
||||
// });
|
||||
|
||||
export function mergeRefs<T = any>(
|
||||
refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>,
|
||||
): React.RefCallback<T> {
|
||||
@ -52,7 +57,8 @@ export function useDrag(options?: any) {
|
||||
left: 0,
|
||||
top: 0,
|
||||
});
|
||||
const dragDropManager = useContext(DragDropManagerContext);
|
||||
const { setDrag, setDrop, getDrop } = useDragDropManagerContext();
|
||||
// const dragDropManager = useContext(DragDropManagerContext);
|
||||
const field = useField();
|
||||
console.log(
|
||||
'init',
|
||||
@ -62,28 +68,26 @@ export function useDrag(options?: any) {
|
||||
|
||||
useWillUnmount(() => {
|
||||
setIsDragging(false);
|
||||
console.log(
|
||||
'useWillUnmount',
|
||||
{ isDragging, previewElement },
|
||||
dragDropManager.previewElement,
|
||||
field ? field.address.segments : null,
|
||||
);
|
||||
// @ts-ignore
|
||||
window.__previewElement && window.__previewElement.remove();
|
||||
// @ts-ignore
|
||||
window.__previewElement = undefined;
|
||||
|
||||
dragDropManager.drag = null;
|
||||
setDrag(null);
|
||||
|
||||
// dragDropManager.drag = null;
|
||||
document.body.style.cursor = null;
|
||||
document.body.style.userSelect = null;
|
||||
})
|
||||
});
|
||||
|
||||
onMouseDown((event: React.MouseEvent) => {
|
||||
if (event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
dragDropManager.drag = { type, item };
|
||||
dragDropManager.drop = { type, item };
|
||||
setDrop({ type, item });
|
||||
setDrag({ type, item });
|
||||
// dragDropManager.drag = { type, item };
|
||||
// dragDropManager.drop = { type, item };
|
||||
setIsDragging(true);
|
||||
|
||||
const postion = {
|
||||
@ -112,7 +116,10 @@ export function useDrag(options?: any) {
|
||||
setPreviewElement(wrap);
|
||||
// @ts-ignore
|
||||
window.__previewElement = wrap;
|
||||
console.log('dragDropManager.previewElement', dragDropManager.previewElement)
|
||||
// console.log(
|
||||
// 'dragDropManager.previewElement',
|
||||
// dragDropManager.previewElement,
|
||||
// );
|
||||
document.body.appendChild(wrap);
|
||||
const el = document.createElement('div');
|
||||
wrap.appendChild(el);
|
||||
@ -122,12 +129,12 @@ export function useDrag(options?: any) {
|
||||
document.body.style.userSelect = 'none';
|
||||
document.body.className = 'dragging';
|
||||
|
||||
console.log(
|
||||
'onMouseDown',
|
||||
{ isDragging, previewElement },
|
||||
dragDropManager.previewElement,
|
||||
field ? field.address.segments : null,
|
||||
);
|
||||
// console.log(
|
||||
// 'onMouseDown',
|
||||
// { isDragging, previewElement },
|
||||
// dragDropManager.previewElement,
|
||||
// field ? field.address.segments : null,
|
||||
// );
|
||||
// console.log('onMouseDown', event);
|
||||
});
|
||||
|
||||
@ -136,17 +143,18 @@ export function useDrag(options?: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
'onMouseUp',
|
||||
{ isDragging, previewElement },
|
||||
field ? field.address.segments : null,
|
||||
);
|
||||
// console.log(
|
||||
// 'onMouseUp',
|
||||
// { isDragging, previewElement },
|
||||
// field ? field.address.segments : null,
|
||||
// );
|
||||
|
||||
// @ts-ignore
|
||||
event.dragItem = item;
|
||||
|
||||
setIsDragging(false);
|
||||
dragDropManager.drag = null;
|
||||
setDrag(null);
|
||||
// dragDropManager.drag = null;
|
||||
previewElement.remove();
|
||||
setPreviewElement(undefined);
|
||||
document.body.style.cursor = null;
|
||||
@ -168,7 +176,8 @@ export function useDrag(options?: any) {
|
||||
continue;
|
||||
}
|
||||
const dropId = dropElement.getAttribute('data-drop-id');
|
||||
const dropContext = dropId ? dragDropManager.drops[dropId] : null;
|
||||
|
||||
const dropContext = getDrop(dropId);
|
||||
if (dropContext && dropContext.accept === type) {
|
||||
if (
|
||||
!dropContext.shallow ||
|
||||
@ -188,12 +197,12 @@ export function useDrag(options?: any) {
|
||||
if (!isDragging || !previewElement) {
|
||||
return;
|
||||
}
|
||||
console.log(
|
||||
'onMouseMove',
|
||||
{ isDragging, previewElement },
|
||||
dragDropManager.previewElement,
|
||||
field ? field.address.segments : null,
|
||||
);
|
||||
// console.log(
|
||||
// 'onMouseMove',
|
||||
// { isDragging, previewElement },
|
||||
// dragDropManager.previewElement,
|
||||
// field ? field.address.segments : null,
|
||||
// );
|
||||
// console.log({previewElement})
|
||||
|
||||
const offset = {
|
||||
@ -205,6 +214,7 @@ export function useDrag(options?: any) {
|
||||
|
||||
if (type) {
|
||||
let dropElement = document.elementFromPoint(event.clientX, event.clientY);
|
||||
console.log({ dropElement });
|
||||
const dropIds = [];
|
||||
while (dropElement) {
|
||||
if (!dropElement.getAttribute) {
|
||||
@ -212,8 +222,9 @@ export function useDrag(options?: any) {
|
||||
continue;
|
||||
}
|
||||
const dropId = dropElement.getAttribute('data-drop-id');
|
||||
const dropContext = dropId ? dragDropManager.drops[dropId] : null;
|
||||
const dropContext = getDrop(dropId);
|
||||
if (dropContext && dropContext.accept === type) {
|
||||
console.log({ dropId });
|
||||
if (
|
||||
!dropContext.shallow ||
|
||||
(dropContext.shallow && dropIds.length === 0)
|
||||
@ -225,7 +236,7 @@ export function useDrag(options?: any) {
|
||||
}
|
||||
dropElement = dropElement.parentNode as HTMLElement;
|
||||
}
|
||||
dragDropManager.drag = { type, dropIds };
|
||||
setDrag({ type, dropIds });
|
||||
}
|
||||
|
||||
onDrag && onDrag(event);
|
||||
@ -235,30 +246,44 @@ export function useDrag(options?: any) {
|
||||
}
|
||||
|
||||
export function useDrop(options) {
|
||||
const { accept, data, shallow, onDrop, onHover, canDrop = true } = options;
|
||||
const {
|
||||
uid: dropId,
|
||||
accept,
|
||||
data,
|
||||
shallow,
|
||||
onDrop,
|
||||
onHover,
|
||||
canDrop = true,
|
||||
} = options;
|
||||
const dropRef = useRef<HTMLDivElement>();
|
||||
const { onMouseEnter, onMouseLeave, onMouseMove, onMouseUp } =
|
||||
useMouseEvents(dropRef);
|
||||
const [isOver, setIsOver] = useState(false);
|
||||
const [onTopHalf, setOnTopHalf] = useState(null);
|
||||
const [dropId] = useState<string>(`d${Math.random()}`);
|
||||
const dragDropManager = useContext(DragDropManagerContext);
|
||||
// const dragDropManager = useContext(DragDropManagerContext);
|
||||
const { drag, drop, addDrop, setDrop } = useDragDropManagerContext();
|
||||
|
||||
useEffect(() => {
|
||||
dragDropManager.drops[dropId] = {
|
||||
addDrop(dropId, {
|
||||
accept,
|
||||
data,
|
||||
shallow,
|
||||
};
|
||||
});
|
||||
// console.log('dragDropManager.drops', dragDropManager.drops);
|
||||
// dragDropManager.drops[dropId] = {
|
||||
// accept,
|
||||
// data,
|
||||
// shallow,
|
||||
// };
|
||||
dropRef.current.setAttribute('data-drop-id', dropId);
|
||||
}, [accept, data, shallow]);
|
||||
}, []);
|
||||
|
||||
onMouseEnter((event) => {
|
||||
if (!canDrop) {
|
||||
return;
|
||||
}
|
||||
// console.log({ dragDropManager });
|
||||
if (!dragDropManager.drag || dragDropManager.drag.type !== accept) {
|
||||
if (!drag || drag.type !== accept) {
|
||||
return;
|
||||
}
|
||||
setIsOver(true);
|
||||
@ -268,13 +293,10 @@ export function useDrop(options) {
|
||||
if (!canDrop) {
|
||||
return;
|
||||
}
|
||||
if (!dragDropManager.drag || dragDropManager.drag.type !== accept) {
|
||||
if (!drag || drag.type !== accept) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
dragDropManager.drag.dropIds &&
|
||||
dragDropManager.drag.dropIds.includes(dropId)
|
||||
) {
|
||||
if (drag.dropIds && drag.dropIds.includes(dropId)) {
|
||||
const top = event.clientY - dropRef.current.getBoundingClientRect().top;
|
||||
const onTop = top < dropRef.current.clientHeight / 2;
|
||||
setOnTopHalf(onTop);
|
||||
@ -303,12 +325,12 @@ export function useDrop(options) {
|
||||
// @ts-ignore
|
||||
event.data = data;
|
||||
// @ts-ignore
|
||||
event.dragItem = dragDropManager.drop.item;
|
||||
event.dragItem = drop.item;
|
||||
// @ts-ignore
|
||||
event.dropElement = dropRef.current;
|
||||
onDrop && onDrop(event);
|
||||
dragDropManager.onDrop && dragDropManager.onDrop(event);
|
||||
dragDropManager.drop = null;
|
||||
// dragDropManager.onDrop && dragDropManager.onDrop(event);
|
||||
setDrop(null);
|
||||
}
|
||||
setIsOver(false);
|
||||
});
|
||||
@ -363,10 +385,12 @@ export function useColResizer(options?: any) {
|
||||
const parent = dragRef.current.parentElement;
|
||||
const els = parent.querySelectorAll(':scope > .nb-grid-col');
|
||||
const size = [];
|
||||
const gap = dragRef.current.clientWidth;
|
||||
console.log('parent.clientWidth', parent.clientWidth, dragRef.current.clientWidth );
|
||||
els.forEach((el: HTMLDivElement) => {
|
||||
const w = (100 * el.clientWidth) / parent.clientWidth;
|
||||
const w2 =
|
||||
(100 * (el.clientWidth + 24 + 24 / els.length)) / parent.clientWidth;
|
||||
(100 * (el.clientWidth + gap + gap / els.length)) / parent.clientWidth;
|
||||
size.push(w2);
|
||||
el.style.width = `${w}%`;
|
||||
});
|
||||
|
@ -5,6 +5,7 @@ import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
// import { DndProvider, useDrag, useDragDropManager } from 'react-dnd';
|
||||
// import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
@ -21,11 +22,12 @@ import './style.less';
|
||||
import cls from 'classnames';
|
||||
|
||||
import { useDesignable, useSchemaPath } from '../DesignableSchemaField';
|
||||
import { useColResizer } from './hooks';
|
||||
import { useDrag, useDrop, DragDropProvider, mergeRefs } from './hooks';
|
||||
import { DragDropManagerProvider, useColResizer } from './hooks';
|
||||
import { useDrag, useDrop, mergeRefs } from './hooks';
|
||||
|
||||
export const GridContext = createContext({
|
||||
ref: null,
|
||||
gridName: null,
|
||||
});
|
||||
|
||||
const ColumnSizeContext = createContext(null);
|
||||
@ -34,9 +36,12 @@ export const GridBlockContext = createContext({
|
||||
dragRef: null,
|
||||
});
|
||||
|
||||
const RowDivider = ({ onDrop }) => {
|
||||
const RowDivider = ({ name, onDrop }) => {
|
||||
const { gridName } = useContext(GridContext);
|
||||
const { isOver, dropRef } = useDrop({
|
||||
accept: 'grid',
|
||||
uid: `row_divider_${name}`,
|
||||
accept: gridName,
|
||||
shallow: true,
|
||||
onDrop,
|
||||
});
|
||||
return (
|
||||
@ -48,11 +53,14 @@ const RowDivider = ({ onDrop }) => {
|
||||
};
|
||||
|
||||
const ColDivider = (props: any) => {
|
||||
const { onDragEnd, resizable } = props;
|
||||
const { name, onDragEnd, resizable, onDrop } = props;
|
||||
const { gridName } = useContext(GridContext);
|
||||
const { isDragging, dragRef } = useColResizer({ onDragEnd });
|
||||
const { isOver, dropRef } = useDrop({
|
||||
accept: 'grid',
|
||||
data: {},
|
||||
uid: `col_divider_${name}`,
|
||||
accept: gridName,
|
||||
shallow: true,
|
||||
onDrop,
|
||||
});
|
||||
return (
|
||||
<div
|
||||
@ -69,59 +77,72 @@ const ColDivider = (props: any) => {
|
||||
};
|
||||
|
||||
export const Grid: any = observer((props) => {
|
||||
const schema = useFieldSchema();
|
||||
const { insertBefore, insertAfter, remove } = useDesignable();
|
||||
const ref = useRef();
|
||||
const schema = useFieldSchema();
|
||||
const gridPath = useSchemaPath();
|
||||
const {
|
||||
schema: designableSchema,
|
||||
insertAfter,
|
||||
prepend,
|
||||
deepRemove,
|
||||
} = useDesignable();
|
||||
return (
|
||||
<DragDropProvider>
|
||||
<GridContext.Provider value={{ ref }}>
|
||||
<DragDropManagerProvider>
|
||||
<GridContext.Provider value={{ ref, gridName: schema.name }}>
|
||||
<div ref={ref} className={'nb-grid'}>
|
||||
<RowDivider
|
||||
key={`${schema.name}_0`}
|
||||
name={`${schema.name}_0`}
|
||||
onDrop={(e) => {
|
||||
const blockSchema = e.dragItem.schema;
|
||||
const path = [...e.dragItem.path];
|
||||
path.pop();
|
||||
remove(path);
|
||||
insertBefore({
|
||||
path.pop();
|
||||
prepend({
|
||||
type: 'void',
|
||||
"x-component": 'Grid.Row',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
"x-component": 'Grid.Col',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[blockSchema.name]: blockSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
deepRemove(path);
|
||||
}}
|
||||
/>
|
||||
{schema.mapProperties((property) => {
|
||||
{schema.mapProperties((property, key, index) => {
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: 'flex' }} className={'nb-grid-row'}>
|
||||
<RecursionField name={property.name} schema={property} />
|
||||
</div>
|
||||
<RowDivider
|
||||
key={`${schema.name}_${index + 1}`}
|
||||
name={`${schema.name}_${index + 1}`}
|
||||
onDrop={(e) => {
|
||||
const blockSchema = e.dragItem.schema;
|
||||
const path = [...e.dragItem.path];
|
||||
path.pop();
|
||||
remove(path);
|
||||
insertAfter({
|
||||
type: 'void',
|
||||
"x-component": 'Grid.Row',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
"x-component": 'Grid.Col',
|
||||
properties: {
|
||||
[blockSchema.name]: blockSchema,
|
||||
insertAfter(
|
||||
{
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Row',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[blockSchema.name]: blockSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
[...gridPath, key],
|
||||
);
|
||||
deepRemove(path);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
@ -129,46 +150,86 @@ export const Grid: any = observer((props) => {
|
||||
})}
|
||||
</div>
|
||||
</GridContext.Provider>
|
||||
</DragDropProvider>
|
||||
</DragDropManagerProvider>
|
||||
);
|
||||
});
|
||||
|
||||
Grid.Row = observer((props) => {
|
||||
const field = useField();
|
||||
const schema = useFieldSchema();
|
||||
const { schema: designableSchema, refresh } = useDesignable();
|
||||
const len = Object.keys(schema.properties || {}).length;
|
||||
const rowPath = useSchemaPath();
|
||||
const {
|
||||
schema: designableSchema,
|
||||
refresh,
|
||||
insertAfter,
|
||||
appendChild,
|
||||
prepend,
|
||||
remove,
|
||||
deepRemove,
|
||||
} = useDesignable();
|
||||
const len = Object.keys(designableSchema.properties || {}).length;
|
||||
console.log({ len });
|
||||
return (
|
||||
<ColumnSizeContext.Provider value={len}>
|
||||
<ColDivider
|
||||
name={`${schema.name}_0`}
|
||||
onDrop={(e) => {
|
||||
const blockSchema = e.dragItem.schema;
|
||||
prepend({
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[blockSchema.name]: blockSchema,
|
||||
},
|
||||
});
|
||||
const path = [...e.dragItem.path];
|
||||
path.pop();
|
||||
deepRemove(path);
|
||||
}}
|
||||
/>
|
||||
{schema.mapProperties((property, key, index) => {
|
||||
return (
|
||||
<>
|
||||
<RecursionField name={property.name} schema={property} />
|
||||
<ColDivider
|
||||
resizable={index > 0}
|
||||
name={`${schema.name}_${index + 1}`}
|
||||
resizable={index < len - 1}
|
||||
onDrop={(e) => {
|
||||
const blockSchema = e.dragItem.schema;
|
||||
insertAfter(
|
||||
{
|
||||
type: 'void',
|
||||
'x-component': 'Grid.Col',
|
||||
properties: {
|
||||
[blockSchema.name]: blockSchema,
|
||||
},
|
||||
},
|
||||
[...rowPath, key],
|
||||
);
|
||||
const path = [...e.dragItem.path];
|
||||
path.pop();
|
||||
deepRemove(path);
|
||||
}}
|
||||
onDragEnd={(e) => {
|
||||
schema.mapProperties((s, key, index) => {
|
||||
field.query(`.${schema.name}.${key}`).take((f) => {
|
||||
f.componentProps['width'] = e.data.size[index];
|
||||
});
|
||||
s['x-component-props'] = s['x-component-props'] || {};
|
||||
s['x-component-props']['width'] = e.data.size[index];
|
||||
return s;
|
||||
});
|
||||
designableSchema.mapProperties((s, key, index) => {
|
||||
s['x-component-props'] = s['x-component-props'] || {};
|
||||
s['x-component-props']['width'] = e.data.size[index];
|
||||
return s;
|
||||
});
|
||||
|
||||
refresh();
|
||||
console.log('e.data', designableSchema);
|
||||
schema.mapProperties((s, key, index) => {
|
||||
s['x-component-props'] = s['x-component-props'] || {};
|
||||
s['x-component-props']['width'] = e.data.size[index];
|
||||
field.query(`.${schema.name}.${key}`).take((f) => {
|
||||
f.componentProps['width'] = e.data.size[index];
|
||||
});
|
||||
return s;
|
||||
});
|
||||
// refresh();
|
||||
}}
|
||||
/>
|
||||
<RecursionField name={property.name} schema={property} />
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<ColDivider />
|
||||
</ColumnSizeContext.Provider>
|
||||
);
|
||||
});
|
||||
@ -179,7 +240,7 @@ Grid.Col = observer((props) => {
|
||||
const size = useContext(ColumnSizeContext);
|
||||
return (
|
||||
<div
|
||||
style={{ width: `calc(${width || 100 / size}% - 24px / ${size})` }}
|
||||
style={{ width: `calc(${width || 100 / size}% - 24px - 24px / ${size})` }}
|
||||
className={'nb-grid-col'}
|
||||
>
|
||||
{props.children}
|
||||
@ -192,7 +253,7 @@ Grid.Block = observer((props) => {
|
||||
const ctx = useContext(GridContext);
|
||||
const path = useSchemaPath();
|
||||
const { isDragging, dragRef, previewRef } = useDrag({
|
||||
type: 'grid',
|
||||
type: ctx.gridName,
|
||||
onDragStart() {
|
||||
console.log('onDragStart');
|
||||
},
|
||||
@ -208,7 +269,8 @@ Grid.Block = observer((props) => {
|
||||
},
|
||||
});
|
||||
const { isOver, onTopHalf, dropRef } = useDrop({
|
||||
accept: 'grid',
|
||||
uid: schema.name,
|
||||
accept: ctx.gridName,
|
||||
data: {},
|
||||
canDrop: !isDragging,
|
||||
});
|
||||
|
@ -9,6 +9,9 @@
|
||||
.nb-grid-col-divider {
|
||||
&.resizable {
|
||||
cursor: col-resize;
|
||||
&:hover {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,11 +19,6 @@
|
||||
.nb-grid.dragging {
|
||||
position: relative;
|
||||
.nb-grid-col-divider {
|
||||
// background-color: #ddd;
|
||||
// opacity: 0.5;
|
||||
&.resizable {
|
||||
cursor: col-resize;
|
||||
}
|
||||
&.hover {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
@ -38,7 +36,7 @@
|
||||
}
|
||||
}
|
||||
.designable-bar {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
.nb-grid-block {
|
||||
position: relative;
|
||||
|
@ -2,7 +2,6 @@ import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useField, observer, RecursionField, Schema } from '@formily/react';
|
||||
import { Dropdown, Menu, Switch } from 'antd';
|
||||
import { useSchemaQuery } from '../grid';
|
||||
import {
|
||||
MenuOutlined,
|
||||
ArrowUpOutlined,
|
||||
@ -11,19 +10,12 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
export const DesignableBar = (props) => {
|
||||
const { schema, addBlock, removeBlock, refresh } = useSchemaQuery();
|
||||
const [active, setActive] = useState(false);
|
||||
const field = useField();
|
||||
return (
|
||||
<>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock(
|
||||
{},
|
||||
{
|
||||
insertBefore: true,
|
||||
},
|
||||
);
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowUpOutlined />}
|
||||
@ -32,7 +24,6 @@ export const DesignableBar = (props) => {
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowDownOutlined />}
|
||||
@ -43,12 +34,9 @@ export const DesignableBar = (props) => {
|
||||
<Menu.Item onClick={() => {}}>
|
||||
<Switch
|
||||
onChange={(checked) => {
|
||||
const key = Object.keys(schema.properties).shift();
|
||||
schema.properties[key].required = checked;
|
||||
refresh();
|
||||
field.query(key).take((target: Formily.Core.Models.Field) => {
|
||||
target.required = checked;
|
||||
});
|
||||
// field.query(key).take((target: Formily.Core.Models.Field) => {
|
||||
// target.required = checked;
|
||||
// });
|
||||
}}
|
||||
checkedChildren="必填"
|
||||
unCheckedChildren="非必填"
|
||||
@ -57,7 +45,6 @@ export const DesignableBar = (props) => {
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
removeBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<DeleteOutlined />}
|
||||
|
@ -2,7 +2,6 @@ import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useField, observer, RecursionField, Schema } from '@formily/react';
|
||||
import { Dropdown, Menu } from 'antd';
|
||||
import { useSchemaQuery } from '../grid';
|
||||
import {
|
||||
MenuOutlined,
|
||||
ArrowUpOutlined,
|
||||
@ -11,18 +10,11 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
export const ColumnDesignableBar = (props) => {
|
||||
const { addBlock, removeBlock } = useSchemaQuery();
|
||||
const [active, setActive] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock(
|
||||
{},
|
||||
{
|
||||
insertBefore: true,
|
||||
},
|
||||
);
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowUpOutlined />}
|
||||
@ -31,7 +23,6 @@ export const ColumnDesignableBar = (props) => {
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowDownOutlined />}
|
||||
@ -41,7 +32,6 @@ export const ColumnDesignableBar = (props) => {
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
removeBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<DeleteOutlined />}
|
||||
|
@ -2,7 +2,6 @@ import React, { useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useField, observer, RecursionField, Schema } from '@formily/react';
|
||||
import { Dropdown, Menu } from 'antd';
|
||||
import { useSchemaQuery } from '../grid';
|
||||
import {
|
||||
MenuOutlined,
|
||||
ArrowUpOutlined,
|
||||
@ -11,18 +10,11 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
|
||||
export const DesignableBar = (props) => {
|
||||
const { addBlock, removeBlock } = useSchemaQuery();
|
||||
const [active, setActive] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock(
|
||||
{},
|
||||
{
|
||||
insertBefore: true,
|
||||
},
|
||||
);
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowUpOutlined />}
|
||||
@ -31,7 +23,6 @@ export const DesignableBar = (props) => {
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
addBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<ArrowDownOutlined />}
|
||||
@ -41,7 +32,6 @@ export const DesignableBar = (props) => {
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
removeBlock();
|
||||
setActive(false);
|
||||
}}
|
||||
icon={<DeleteOutlined />}
|
||||
|
Loading…
Reference in New Issue
Block a user