123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- import DragMoveFoundation, { DragMoveAdapter } from '@douyinfe/semi-foundation/dragMove/foundation';
- import BaseComponent from '../_base/baseComponent';
- import { ReactNode } from 'react';
- import PropTypes from 'prop-types';
- import React from 'react';
- import { isHTMLElement } from '../_base/reactUtils';
- import ReactDOM from 'react-dom';
- export interface DragMoveProps {
- // The element that triggers the drag event,default is element
- handler?: () => ReactNode;
- // The element that constrains the movement range, This element requires relative positioning
- constrainer?: () => ReactNode | 'parent';
- children?: ReactNode | undefined | any;
- onMouseDown?: (e: MouseEvent) => void;
- onMouseMove?: (e: MouseEvent) => void;
- onMouseUp?: (e: MouseEvent) => void;
- onTouchStart?: (e: TouchEvent) => void;
- onTouchMove?: (e: TouchEvent) => void;
- onTouchEnd?: (e: TouchEvent) => void;
- onTouchCancel?: (e: TouchEvent) => void;
- // Determine whether dragging is triggered when the mouse is pressed.
- // Return true to trigger dragging. Return false to not trigger dragging.
- allowMove?: (e: MouseEvent | TouchEvent, element: HTMLElement) => boolean;
- // customize move behavior
- customMove?: (e: HTMLElement, top: number, left: number) => void
- }
- export default class DragMove extends BaseComponent<DragMoveProps, null> {
-
- static propTypes = {
- children: PropTypes.node,
- handler: PropTypes.func,
- allowInputDrag: PropTypes.bool,
- constrainNode: PropTypes.func,
- onMouseDown: PropTypes.func,
- onMouseMove: PropTypes.func,
- onMouseUp: PropTypes.func,
- onTouchStart: PropTypes.func,
- onTouchMove: PropTypes.func,
- onTouchEnd: PropTypes.func,
- onTouchCancel: PropTypes.func,
- }
- static __SemiComponentName__ = "DragMove";
- static defaultProps = {
- allowInputDrag: false,
- };
- constructor(props: DragMoveProps) {
- super(props);
- this.elementRef = React.createRef();
- this.foundation = new DragMoveFoundation(this.adapter);
- }
- elementRef: React.RefObject<unknown>;
- foundation: DragMoveFoundation;
- get adapter(): DragMoveAdapter<DragMoveProps, null> {
- return {
- ...super.adapter,
- getDragElement: () => {
- let elementDom = this.elementRef.current;
- if (!isHTMLElement(elementDom)) {
- elementDom = ReactDOM.findDOMNode(elementDom as React.ReactInstance);
- }
- return elementDom as HTMLElement;
- },
- getConstrainer: () => {
- const { constrainer } = this.props;
- if (typeof constrainer === 'string' && constrainer === 'parent') {
- return (this.elementRef.current as HTMLElement)?.parentNode as HTMLElement;
- } else if (typeof constrainer === 'function') {
- return constrainer() as any;
- } else {
- return null;
- }
- },
- getHandler: () => {
- const { handler } = this.props;
- if (typeof handler === 'function') {
- return handler() as any;
- } else {
- return this.adapter.getDragElement() as HTMLElement;
- }
- },
- notifyMouseDown: (e: MouseEvent) => {
- this.props.onMouseDown && this.props.onMouseDown(e);
- },
- notifyMouseMove: (e: MouseEvent) => {
- this.props.onMouseMove && this.props.onMouseMove(e);
- },
- notifyMouseUp: (e: MouseEvent) => {
- this.props.onMouseUp && this.props.onMouseUp(e);
- },
- notifyTouchStart: (e: TouchEvent) => {
- this.props.onTouchStart && this.props.onTouchStart(e);
- },
- notifyTouchMove: (e: TouchEvent) => {
- this.props.onTouchMove && this.props.onTouchMove(e);
- },
- notifyTouchEnd: (e: TouchEvent) => {
- this.props.onTouchEnd && this.props.onTouchEnd(e);
- },
- notifyTouchCancel: (e: TouchEvent) => {
- this.props.onTouchCancel && this.props.onTouchCancel(e);
- },
- };
- }
- componentDidMount(): void {
- this.foundation.init();
- }
- componentWillUnmount(): void {
- this.foundation.destroy();
- }
- render() {
- const { children } = this.props;
- const newChildren = React.cloneElement(children, {
- ref: (node: React.ReactNode) => {
- (this.elementRef as any).current = node;
- // Call the original ref, if any
- const { ref } = children as any;
- if (typeof ref === 'function') {
- ref(node);
- } else if (ref && typeof ref === 'object') {
- ref.current = node;
- }
- },
- });
- return newChildren;
- }
- }
-
|