import * as React from 'react' import checkDecoratorArguments from './utils/checkDecoratorArguments' import { DragDropManager, Unsubscribe } from '../dnd-core' import { DragLayerCollector, DndOptions, DndComponentClass } from './interfaces' import { manager } from './DragDropContext' // import {IResizeMonitor} from '../resize/interfaces'; // import {IRotateMonitor} from '../rotate/interfaces'; // import createDragMonitor from './createSourceMonitor'; // import createResizeMonitor from '../resize/createSourceMonitor' // import createRotateMonitor from '../rotate/createSourceMonitor' import {SourceMonitor as DragMonitor} from './createSourceMonitor' import {ResizeMonitor} from '../resize/createSourceMonitor' import {RotateMonitor} from '../rotate/createSourceMonitor' import {extend} from './utils/extend' const hoistStatics = require('hoist-non-react-statics') const isPlainObject = require('lodash/isPlainObject') const invariant = require('invariant') const shallowEqual = require('shallowequal') const isClassComponent = require('recompose/isClassComponent').default // export default function layerFactory (createSourceMonitor: any) { // return // } const MixMonitor: any = extend(DragMonitor, ResizeMonitor, RotateMonitor); const mixMonitor = new MixMonitor(manager); export default function DragLayer( collect: DragLayerCollector, options: DndOptions = {}, ) { checkDecoratorArguments('DragLayer', 'collect[, options]', collect, options) invariant( typeof collect === 'function', 'Expected "collect" provided as the first argument to DragLayer to be a function that collects props to inject into the component. ', 'Instead, received %s. Read more: http://react-dnd.github.io/react-dnd/docs-drag-layer.html', collect, ) invariant( isPlainObject(options), 'Expected "options" provided as the second argument to DragLayer to be a plain object when specified. ' + 'Instead, received %s. Read more: http://react-dnd.github.io/react-dnd/docs-drag-layer.html', options, ) return function decorateLayer< TargetClass extends | React.ComponentClass | React.StatelessComponent >(DecoratedComponent: TargetClass): TargetClass & DndComponentClass { const Decorated = DecoratedComponent as any const { arePropsEqual = shallowEqual } = options const displayName = Decorated.displayName || Decorated.name || 'Component' class DragLayerContainer extends React.Component { public static displayName = `DragLayer(${displayName})` public get DecoratedComponent() { return DecoratedComponent } // private manager: DragDropManager | undefined private monitor: any private isCurrentlyMounted: boolean = false private unsubscribeFromOffsetChange: Unsubscribe | undefined private unsubscribeFromStateChange: Unsubscribe | undefined private ref: React.RefObject = React.createRef() constructor(props: Props) { super(props) // const monitor = [createDragMonitor(manager), createResizeMonitor(manager), createRotateMonitor(manager)]; this.receiveDragDropManager(mixMonitor); // this.handleChange = this.handleChange.bind(this) } public getDecoratedComponentInstance() { invariant( this.ref.current, 'In order to access an instance of the decorated component it can not be a stateless component.', ) return this.ref.current } public shouldComponentUpdate(nextProps: any, nextState: any) { return ( !arePropsEqual(nextProps, this.props) || !shallowEqual(nextState, this.state) ) } public componentDidMount() { this.isCurrentlyMounted = true this.handleChange() } public componentWillUnmount() { this.isCurrentlyMounted = false if (this.unsubscribeFromOffsetChange) { this.unsubscribeFromOffsetChange() this.unsubscribeFromOffsetChange = undefined } if (this.unsubscribeFromStateChange) { this.unsubscribeFromStateChange() this.unsubscribeFromStateChange = undefined } } public render() { // if (!this.isCurrentlyMounted) { // return null // } return ( ) } private receiveDragDropManager(monitor: any) { if (this.monitor !== undefined) { return } this.monitor = monitor; // invariant( // typeof dragDropManager === 'object', // 'Could not find the drag and drop manager in the context of %s. ' + // 'Make sure to wrap the top-level component of your app with DragDropContext. ' + // 'Read more: http://react-dnd.github.io/react-dnd/docs-troubleshooting.html#could-not-find-the-drag-and-drop-manager-in-the-context', // displayName, // displayName, // ) // const monitor = this.manager.getMonitor() // const [dragMonitor] = monitor; this.unsubscribeFromOffsetChange = monitor.subscribeToOffsetChange( this.handleChange, ) this.unsubscribeFromStateChange = monitor.subscribeToStateChange( this.handleChange, ) } private handleChange = () => { if (!this.isCurrentlyMounted) { return } const nextState = this.getCurrentState() if (!shallowEqual(nextState, this.state)) { this.setState(nextState) } } private getCurrentState() { if (!this.monitor) { return {} } // const [dragMonitor, resizeMonitor, rotateMonitor ] = this.monitor; // let monitor = dragMonitor; // if (resizeMonitor.isResizing()) monitor = resizeMonitor; // if (rotateMonitor.isRotating()) monitor = rotateMonitor; // const monitor = this.manager.getMonitor() return collect(this.monitor, this.props); } } return hoistStatics(DragLayerContainer, DecoratedComponent) as TargetClass & DndComponentClass } }