refactor: useDrag & useDrop & useColResize
This commit is contained in:
		
							parent
							
								
									3c3ae5c348
								
							
						
					
					
						commit
						a7fd94affd
					
				@ -23,6 +23,7 @@
 | 
				
			|||||||
    "@formily/react": "^2.0.0-beta.54",
 | 
					    "@formily/react": "^2.0.0-beta.54",
 | 
				
			||||||
    "ahooks": "^2.10.2",
 | 
					    "ahooks": "^2.10.2",
 | 
				
			||||||
    "axios": "^0.21.1",
 | 
					    "axios": "^0.21.1",
 | 
				
			||||||
 | 
					    "beautiful-react-hooks": "^0.35.0",
 | 
				
			||||||
    "lodash": "^4.17.21",
 | 
					    "lodash": "^4.17.21",
 | 
				
			||||||
    "react-dnd": "^14.0.2",
 | 
					    "react-dnd": "^14.0.2",
 | 
				
			||||||
    "react-dnd-html5-backend": "^14.0.0",
 | 
					    "react-dnd-html5-backend": "^14.0.0",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										87
									
								
								packages/client/src/blocks/grid/Col.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								packages/client/src/blocks/grid/Col.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					import React, { useRef, useState } from 'react';
 | 
				
			||||||
 | 
					import { useMouseEvents } from 'beautiful-react-hooks';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useColResizer(options?: any) {
 | 
				
			||||||
 | 
					  const { onDragStart, onDrag, onDragEnd } = options || {};
 | 
				
			||||||
 | 
					  const dragRef = useRef<HTMLDivElement>();
 | 
				
			||||||
 | 
					  const [dragOffset, setDragOffset] = useState({ left: 0, top: 0 });
 | 
				
			||||||
 | 
					  const { onMouseDown } = useMouseEvents(dragRef);
 | 
				
			||||||
 | 
					  const { onMouseMove, onMouseUp } = useMouseEvents();
 | 
				
			||||||
 | 
					  const [isDragging, setIsDragging] = useState(false);
 | 
				
			||||||
 | 
					  const [columns, setColumns] = useState(options.columns || []);
 | 
				
			||||||
 | 
					  const [initial, setInitial] = useState<any>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseDown((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    setIsDragging(true);
 | 
				
			||||||
 | 
					    const prev = dragRef.current.previousElementSibling as HTMLDivElement;
 | 
				
			||||||
 | 
					    const next = dragRef.current.nextElementSibling as HTMLDivElement;
 | 
				
			||||||
 | 
					    if (!initial) {
 | 
				
			||||||
 | 
					      setInitial({
 | 
				
			||||||
 | 
					        offset: event.clientX,
 | 
				
			||||||
 | 
					        prevWidth: prev.style.width,
 | 
				
			||||||
 | 
					        nextWidth: next.style.width,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseUp((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    if (!isDragging) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const parent = dragRef.current.parentElement;
 | 
				
			||||||
 | 
					    const els = parent.querySelectorAll('.col');
 | 
				
			||||||
 | 
					    const size = [];
 | 
				
			||||||
 | 
					    els.forEach((el: HTMLDivElement) => {
 | 
				
			||||||
 | 
					      const w = el.clientWidth / parent.clientWidth;
 | 
				
			||||||
 | 
					      size.push(w);
 | 
				
			||||||
 | 
					      el.style.width = `${100 * w}%`;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    console.log(size);
 | 
				
			||||||
 | 
					    setIsDragging(false);
 | 
				
			||||||
 | 
					    setInitial(null);
 | 
				
			||||||
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    event.data = { size };
 | 
				
			||||||
 | 
					    onDragEnd(event);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseMove((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    if (!isDragging) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const offset = event.clientX - initial.offset;
 | 
				
			||||||
 | 
					    // dragRef.current.style.transform = `translateX(${event.clientX - initialOffset}px)`;
 | 
				
			||||||
 | 
					    const prev = dragRef.current.previousElementSibling as HTMLDivElement;
 | 
				
			||||||
 | 
					    const next = dragRef.current.nextElementSibling as HTMLDivElement;
 | 
				
			||||||
 | 
					    prev.style.width = `calc(${initial.prevWidth} + ${offset}px)`;
 | 
				
			||||||
 | 
					    next.style.width = `calc(${initial.nextWidth} - ${offset}px)`;
 | 
				
			||||||
 | 
					    // console.log('dragRef.current.nextSibling', prev.style.width);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { dragOffset, dragRef, columns };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Col: any = (props) => {
 | 
				
			||||||
 | 
					  const { size, children } = props;
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      className={'col'}
 | 
				
			||||||
 | 
					      style={{ width: `${size * 100}%` }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {children}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Col.Divider = (props) => {
 | 
				
			||||||
 | 
					  const { onDragEnd } = props;
 | 
				
			||||||
 | 
					  const { dragRef } = useColResizer({ onDragEnd });
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      className={'col-divider'}
 | 
				
			||||||
 | 
					      style={{ width: '24px', cursor: 'col-resize' }}
 | 
				
			||||||
 | 
					      ref={dragRef}
 | 
				
			||||||
 | 
					    ></div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Col;
 | 
				
			||||||
							
								
								
									
										224
									
								
								packages/client/src/blocks/grid/DND.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								packages/client/src/blocks/grid/DND.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,224 @@
 | 
				
			|||||||
 | 
					import React, { createContext, useContext, useEffect, useRef } from 'react';
 | 
				
			||||||
 | 
					import { useState } from 'react';
 | 
				
			||||||
 | 
					import { useMouseEvents } from 'beautiful-react-hooks';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const DragDropManagerContext = createContext({ drag: null, drops: {} });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function DragDropProvider({ children }) {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <DragDropManagerContext.Provider
 | 
				
			||||||
 | 
					      value={{
 | 
				
			||||||
 | 
					        drag: null,
 | 
				
			||||||
 | 
					        drops: {},
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {children}
 | 
				
			||||||
 | 
					    </DragDropManagerContext.Provider>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function mergeRefs<T = any>(
 | 
				
			||||||
 | 
					  refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>
 | 
				
			||||||
 | 
					): React.RefCallback<T> {
 | 
				
			||||||
 | 
					  return (value) => {
 | 
				
			||||||
 | 
					    refs.forEach((ref) => {
 | 
				
			||||||
 | 
					      if (typeof ref === "function") {
 | 
				
			||||||
 | 
					        ref(value);
 | 
				
			||||||
 | 
					      } else if (ref != null) {
 | 
				
			||||||
 | 
					        (ref as React.MutableRefObject<T | null>).current = value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useDrag(options?: any) {
 | 
				
			||||||
 | 
					  const { type, onDragStart, onDrag, onDragEnd } = options;
 | 
				
			||||||
 | 
					  const dragRef = useRef<HTMLButtonElement>();
 | 
				
			||||||
 | 
					  const previewRef = useRef<HTMLDivElement>();
 | 
				
			||||||
 | 
					  const [dragOffset, setDragOffset] = useState({ left: 0, top: 0 });
 | 
				
			||||||
 | 
					  const [previewOffset, setPreviewOffset] = useState({ left: 0, top: 0 });
 | 
				
			||||||
 | 
					  const { onMouseDown } = useMouseEvents(dragRef);
 | 
				
			||||||
 | 
					  const { onMouseMove, onMouseUp } = useMouseEvents();
 | 
				
			||||||
 | 
					  const [previewElement, setPreviewElement] = useState<HTMLDivElement>();
 | 
				
			||||||
 | 
					  const [isDragging, setIsDragging] = useState(false);
 | 
				
			||||||
 | 
					  const dragDropManager = useContext(DragDropManagerContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseDown((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    dragDropManager.drag = { type };
 | 
				
			||||||
 | 
					    setIsDragging(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const offset = {
 | 
				
			||||||
 | 
					      left: event.clientX - previewRef.current.offsetLeft,
 | 
				
			||||||
 | 
					      top: event.clientY - previewRef.current.offsetTop,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    setDragOffset(offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const offset2 = {
 | 
				
			||||||
 | 
					      left: event.clientX - offset.left,
 | 
				
			||||||
 | 
					      top: event.clientY - offset.top,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    setPreviewOffset(offset2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log('previewRef.current.clientWidth', previewRef.current.clientWidth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const wrap = document.createElement('div');
 | 
				
			||||||
 | 
					    wrap.style.position = 'absolute';
 | 
				
			||||||
 | 
					    wrap.style.pointerEvents = 'none';
 | 
				
			||||||
 | 
					    wrap.style.opacity = '0.7';
 | 
				
			||||||
 | 
					    wrap.style.left = `0px`;
 | 
				
			||||||
 | 
					    wrap.style.top = `0px`;
 | 
				
			||||||
 | 
					    wrap.style.zIndex = '9999';
 | 
				
			||||||
 | 
					    wrap.style.width = `${previewRef.current.clientWidth}px`;
 | 
				
			||||||
 | 
					    wrap.style.transform = `translate(${offset2.left}px, ${offset2.top}px)`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setPreviewElement(wrap);
 | 
				
			||||||
 | 
					    document.body.appendChild(wrap);
 | 
				
			||||||
 | 
					    const el = document.createElement('div');
 | 
				
			||||||
 | 
					    wrap.appendChild(el);
 | 
				
			||||||
 | 
					    el.outerHTML = previewRef.current.outerHTML;
 | 
				
			||||||
 | 
					    onDragStart && onDragStart(event);
 | 
				
			||||||
 | 
					    document.body.style.cursor = 'grab';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    console.log('onMouseDown', dragDropManager);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseUp((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    setIsDragging(false);
 | 
				
			||||||
 | 
					    dragDropManager.drag = null;
 | 
				
			||||||
 | 
					    if (!previewElement) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    previewElement.remove();
 | 
				
			||||||
 | 
					    document.body.style.cursor = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (type) {
 | 
				
			||||||
 | 
					      let dropElement = document.elementFromPoint(event.clientX, event.clientY);
 | 
				
			||||||
 | 
					      const dropIds = [];
 | 
				
			||||||
 | 
					      while (dropElement) {
 | 
				
			||||||
 | 
					        if (!dropElement.getAttribute) {
 | 
				
			||||||
 | 
					          dropElement = dropElement.parentNode as Element;
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const dropId = dropElement.getAttribute('data-drop-id');
 | 
				
			||||||
 | 
					        const dropContext = dropId ? dragDropManager.drops[dropId] : null;
 | 
				
			||||||
 | 
					        if (dropContext && dropContext.accept === type) {
 | 
				
			||||||
 | 
					          if (
 | 
				
			||||||
 | 
					            !dropContext.shallow ||
 | 
				
			||||||
 | 
					            (dropContext.shallow && dropIds.length === 0)
 | 
				
			||||||
 | 
					          ) {
 | 
				
			||||||
 | 
					            // @ts-ignore
 | 
				
			||||||
 | 
					            event.data = dropContext.data;
 | 
				
			||||||
 | 
					            onDragEnd && onDragEnd(event);
 | 
				
			||||||
 | 
					            dropIds.push(dropId);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        dropElement = dropElement.parentNode as Element;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      onDragEnd && onDragEnd(event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseMove((event: React.MouseEvent) => {
 | 
				
			||||||
 | 
					    if (!isDragging) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!previewElement) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const offset = {
 | 
				
			||||||
 | 
					      left: event.clientX - dragOffset.left,
 | 
				
			||||||
 | 
					      top: event.clientY - dragOffset.top,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setPreviewOffset(offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    previewElement.style.transform = `translate(${offset.left}px, ${offset.top}px)`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (type) {
 | 
				
			||||||
 | 
					      let dropElement = document.elementFromPoint(event.clientX, event.clientY);
 | 
				
			||||||
 | 
					      const dropIds = [];
 | 
				
			||||||
 | 
					      while (dropElement) {
 | 
				
			||||||
 | 
					        if (!dropElement.getAttribute) {
 | 
				
			||||||
 | 
					          dropElement = dropElement.parentNode as Element;
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const dropId = dropElement.getAttribute('data-drop-id');
 | 
				
			||||||
 | 
					        const dropContext = dropId ? dragDropManager.drops[dropId] : null;
 | 
				
			||||||
 | 
					        if (dropContext && dropContext.accept === type) {
 | 
				
			||||||
 | 
					          if (
 | 
				
			||||||
 | 
					            !dropContext.shallow ||
 | 
				
			||||||
 | 
					            (dropContext.shallow && dropIds.length === 0)
 | 
				
			||||||
 | 
					          ) {
 | 
				
			||||||
 | 
					            dropIds.push(dropId);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          // @ts-ignore
 | 
				
			||||||
 | 
					          // event.data = dropContext.data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        dropElement = dropElement.parentNode as Element;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      dragDropManager.drag = { type, dropIds };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    onDrag && onDrag(event);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { isDragging, previewOffset, dragOffset, dragRef, previewRef };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useDrop(options) {
 | 
				
			||||||
 | 
					  const { accept, data, shallow } = options;
 | 
				
			||||||
 | 
					  const dropRef = useRef<HTMLDivElement>();
 | 
				
			||||||
 | 
					  const { onMouseEnter, onMouseLeave, onMouseMove, onMouseUp } =
 | 
				
			||||||
 | 
					    useMouseEvents(dropRef);
 | 
				
			||||||
 | 
					  const [isOver, setIsOver] = useState(false);
 | 
				
			||||||
 | 
					  const [dropId] = useState<string>(`d${Math.random()}`);
 | 
				
			||||||
 | 
					  const dragDropManager = useContext(DragDropManagerContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    dragDropManager.drops[dropId] = {
 | 
				
			||||||
 | 
					      accept,
 | 
				
			||||||
 | 
					      data,
 | 
				
			||||||
 | 
					      shallow,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    dropRef.current.setAttribute('data-drop-id', dropId);
 | 
				
			||||||
 | 
					  }, [accept, data, shallow]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseEnter((event) => {
 | 
				
			||||||
 | 
					    console.log({ dragDropManager });
 | 
				
			||||||
 | 
					    if (!dragDropManager.drag || dragDropManager.drag.type !== accept) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    setIsOver(true);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseMove(() => {
 | 
				
			||||||
 | 
					    if (!dragDropManager.drag || dragDropManager.drag.type !== accept) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					      dragDropManager.drag.dropIds &&
 | 
				
			||||||
 | 
					      dragDropManager.drag.dropIds.includes(dropId)
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					      setIsOver(true);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      setIsOver(false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseUp((event) => {
 | 
				
			||||||
 | 
					    setIsOver(false);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onMouseLeave(() => {
 | 
				
			||||||
 | 
					    setIsOver(false);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    isOver,
 | 
				
			||||||
 | 
					    dropRef,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								packages/client/src/blocks/grid/Row.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/client/src/blocks/grid/Row.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import { Col } from './Col';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const Row = (props) => {
 | 
				
			||||||
 | 
					  const { children, onColResize } = props;
 | 
				
			||||||
 | 
					  const len = children.length;
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div style={{ display: 'flex' }}>
 | 
				
			||||||
 | 
					      {children.map((child, index) => {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					          <>
 | 
				
			||||||
 | 
					            {child}
 | 
				
			||||||
 | 
					            {len > index + 1 && <Col.Divider onDragEnd={onColResize} />}
 | 
				
			||||||
 | 
					          </>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      })}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Row;
 | 
				
			||||||
							
								
								
									
										109
									
								
								packages/client/src/blocks/grid/demos/demo4.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								packages/client/src/blocks/grid/demos/demo4.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					import React, { createContext, useContext, useEffect, useRef } from 'react';
 | 
				
			||||||
 | 
					import { useDrag, useDrop, DragDropProvider } from '../';
 | 
				
			||||||
 | 
					import { Button, Space } from 'antd';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function DropZone({ options, children }) {
 | 
				
			||||||
 | 
					  const { isOver, dropRef } = useDrop(options);
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div
 | 
				
			||||||
 | 
					      ref={dropRef}
 | 
				
			||||||
 | 
					      style={{
 | 
				
			||||||
 | 
					        textAlign: 'center',
 | 
				
			||||||
 | 
					        lineHeight: '100px',
 | 
				
			||||||
 | 
					        margin: 24,
 | 
				
			||||||
 | 
					        border: isOver ? '1px solid red' : '1px solid #ddd',
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {children}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Dragable() {
 | 
				
			||||||
 | 
					  const { isDragging, dragRef, previewRef } = useDrag({
 | 
				
			||||||
 | 
					    type: 'box',
 | 
				
			||||||
 | 
					    onDragStart() {
 | 
				
			||||||
 | 
					      console.log('onDragStart');
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    onDragEnd(event) {
 | 
				
			||||||
 | 
					      console.log('onDragEnd', event.data);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    onDrag(event) {
 | 
				
			||||||
 | 
					      // console.log('onDrag');
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Button ref={mergeRefs<any>([dragRef, previewRef])}>拖拽1</Button>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function mergeRefs<T = any>(
 | 
				
			||||||
 | 
					  refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>
 | 
				
			||||||
 | 
					): React.RefCallback<T> {
 | 
				
			||||||
 | 
					  return (value) => {
 | 
				
			||||||
 | 
					    refs.forEach((ref) => {
 | 
				
			||||||
 | 
					      if (typeof ref === "function") {
 | 
				
			||||||
 | 
					        ref(value);
 | 
				
			||||||
 | 
					      } else if (ref != null) {
 | 
				
			||||||
 | 
					        (ref as React.MutableRefObject<T | null>).current = value;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function Dragable2() {
 | 
				
			||||||
 | 
					  const { isDragging, dragRef, previewRef } = useDrag({
 | 
				
			||||||
 | 
					    type: 'box2',
 | 
				
			||||||
 | 
					    onDragStart() {
 | 
				
			||||||
 | 
					      console.log('onDragStart');
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    onDragEnd(event) {
 | 
				
			||||||
 | 
					      console.log('onDragEnd', event.data);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    onDrag(event) {
 | 
				
			||||||
 | 
					      // console.log('onDrag');
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Button ref={mergeRefs<any>([dragRef, previewRef])}>拖拽2</Button>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <DragDropProvider>
 | 
				
			||||||
 | 
					      <Space style={{marginBottom: 12}}>
 | 
				
			||||||
 | 
					      <Dragable />
 | 
				
			||||||
 | 
					      <Dragable2 />
 | 
				
			||||||
 | 
					      </Space>
 | 
				
			||||||
 | 
					      <DropZone
 | 
				
			||||||
 | 
					        options={{
 | 
				
			||||||
 | 
					          accept: 'box',
 | 
				
			||||||
 | 
					          data: { a: 'a' },
 | 
				
			||||||
 | 
					          shallow: true,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        Drop Zone1
 | 
				
			||||||
 | 
					        <DropZone
 | 
				
			||||||
 | 
					          options={{
 | 
				
			||||||
 | 
					            accept: 'box',
 | 
				
			||||||
 | 
					            data: { b: 'b' },
 | 
				
			||||||
 | 
					            // shallow: true,
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          Drop Zone2
 | 
				
			||||||
 | 
					        </DropZone>
 | 
				
			||||||
 | 
					        <DropZone
 | 
				
			||||||
 | 
					          options={{
 | 
				
			||||||
 | 
					            accept: 'box2',
 | 
				
			||||||
 | 
					            data: { c: 'c' },
 | 
				
			||||||
 | 
					            // shallow: true,
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          Drop Zone3
 | 
				
			||||||
 | 
					        </DropZone>
 | 
				
			||||||
 | 
					        Drop Zone1
 | 
				
			||||||
 | 
					      </DropZone>
 | 
				
			||||||
 | 
					    </DragDropProvider>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										16
									
								
								packages/client/src/blocks/grid/demos/demo5.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								packages/client/src/blocks/grid/demos/demo5.less
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					.col-divider {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  &:hover {
 | 
				
			||||||
 | 
					    &::after {
 | 
				
			||||||
 | 
					      content: '';
 | 
				
			||||||
 | 
					      display: block;
 | 
				
			||||||
 | 
					      position: absolute;
 | 
				
			||||||
 | 
					      top: 0;
 | 
				
			||||||
 | 
					      left: 50%;
 | 
				
			||||||
 | 
					      transform: translateX(-50%);
 | 
				
			||||||
 | 
					      height: 100%;
 | 
				
			||||||
 | 
					      width: 12px;
 | 
				
			||||||
 | 
					      background: #e6f7ff;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								packages/client/src/blocks/grid/demos/demo5.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								packages/client/src/blocks/grid/demos/demo5.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import { Row, Col } from '../';
 | 
				
			||||||
 | 
					import './demo5.less';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default () => {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					      <Row onColResize={(e) => {
 | 
				
			||||||
 | 
					        console.log(e.data);
 | 
				
			||||||
 | 
					      }}>
 | 
				
			||||||
 | 
					        {[1, 2, 3].map((index) => (
 | 
				
			||||||
 | 
					          <Col size={1 / 3}>
 | 
				
			||||||
 | 
					            <div style={{textAlign: 'center', lineHeight: '60px', background: '#f1f1f1'}}>col {index}</div>
 | 
				
			||||||
 | 
					          </Col>
 | 
				
			||||||
 | 
					        ))}
 | 
				
			||||||
 | 
					      </Row>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -23,6 +23,14 @@ group:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<code src="./demos/demo3.tsx"/>
 | 
					<code src="./demos/demo3.tsx"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### useDrag & useDrop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<code src="./demos/demo4.tsx"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### useColResize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<code src="./demos/demo5.tsx"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## API 说明
 | 
					## API 说明
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Grid
 | 
					### Grid
 | 
				
			||||||
@ -57,4 +65,11 @@ interface BlockOptions {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### blocks2properties
 | 
					### blocks2properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
原始 schema 需要至少 grid->row->col->block->custom 五层嵌套,写起来非常繁琐,`blocks2properties` 方法可以简化配置。
 | 
					原始 schema 需要至少 grid->row->col->block->custom 五层嵌套,写起来非常繁琐,`blocks2properties` 方法可以简化配置。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### useDrag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### useDrop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### useColResize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					export * from './Row';
 | 
				
			||||||
 | 
					export * from './Col';
 | 
				
			||||||
 | 
					export * from './DND';
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user