import * as React from 'react' import { DragDropManager, BackendFactory, createDragDropManager, } from '../dnd-core' import checkDecoratorArguments from './utils/checkDecoratorArguments' import { ContextComponent } from './interfaces' import DragDropManagerImpl from '../dnd-core/DragDropManagerImpl'; import createHTML5Backend from '../react-dnd-html5-backend'; const invariant = require('invariant') const hoistStatics = require('hoist-non-react-statics') const isClassComponent = require('recompose/isClassComponent').default /** * The React context type */ export interface DragDropContext { dragDropManager: DragDropManager | undefined } /** * Create the React Context */ export const { Consumer, Provider } = React.createContext>( { dragDropManager: undefined }, ) /** * Creates the context object we're providing * @param backend * @param context */ export function createChildContext( backend: BackendFactory, context?: BackendContext, ) { return { dragDropManager: createDragDropManager(backend, context), } } export interface DragDropContextProviderProps { backend: BackendFactory context?: BackendContext } /** * A React component that provides the React-DnD context */ export const DragDropContextProvider: React.SFC< DragDropContextProviderProps > = ({ backend, context, children }) => { const contextValue = createChildContext(backend, context) return {children} } /** * Wrap the root component of your application with DragDropContext decorator to set up React DnD. * This lets you specify the backend, and sets up the shared DnD state behind the scenes. * @param backendFactory The DnD backend factory * @param backendContext The backend context */ export function DragDropContext( backendFactory: BackendFactory, backendContext?: any, ) { checkDecoratorArguments('DragDropContext', 'backend', backendFactory) const childContext = createChildContext(backendFactory, backendContext) return function decorateContext< TargetClass extends | React.ComponentClass | React.StatelessComponent >(DecoratedComponent: TargetClass): TargetClass & ContextComponent { const Decorated = DecoratedComponent as any const displayName = Decorated.displayName || Decorated.name || 'Component' class DragDropContextContainer extends React.Component implements ContextComponent { public static DecoratedComponent = DecoratedComponent public static displayName = `DragDropContext(${displayName})` private ref: React.RefObject = React.createRef() 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 getManager() { return childContext.dragDropManager } public render() { return ( ) } } return hoistStatics( DragDropContextContainer, DecoratedComponent, ) as TargetClass & DragDropContextContainer } } export const manager = createDragDropManager(createHTML5Backend, {});