From 632a1775b60801a7269626c3c89c13db2ea83ef1 Mon Sep 17 00:00:00 2001 From: Haff Date: Thu, 25 Nov 2021 15:01:32 +0100 Subject: [PATCH 1/2] Make DragLayerMonitor generic --- packages/react-dnd/src/decorators/DragLayer.tsx | 4 ++-- packages/react-dnd/src/decorators/types.ts | 4 ++-- packages/react-dnd/src/hooks/useDragLayer.ts | 4 ++-- packages/react-dnd/src/types/monitors.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-dnd/src/decorators/DragLayer.tsx b/packages/react-dnd/src/decorators/DragLayer.tsx index 170efc5eb8..86b25378bc 100644 --- a/packages/react-dnd/src/decorators/DragLayer.tsx +++ b/packages/react-dnd/src/decorators/DragLayer.tsx @@ -16,8 +16,8 @@ import { isRefable, checkDecoratorArguments, isPlainObject } from './utils' * @param collect The props collector function * @param options The DnD options */ -export function DragLayer( - collect: DragLayerCollector, +export function DragLayer( + collect: DragLayerCollector, options: DndOptions = {}, ): DndComponentEnhancer { checkDecoratorArguments('DragLayer', 'collect[, options]', collect, options) diff --git a/packages/react-dnd/src/decorators/types.ts b/packages/react-dnd/src/decorators/types.ts index fcedaaa6ce..c6d71d8d31 100644 --- a/packages/react-dnd/src/decorators/types.ts +++ b/packages/react-dnd/src/decorators/types.ts @@ -176,8 +176,8 @@ export type DropTargetCollector = ( props: TargetProps, ) => CollectedProps -export type DragLayerCollector = ( - monitor: DragLayerMonitor, +export type DragLayerCollector = ( + monitor: DragLayerMonitor, props: TargetProps, ) => CollectedProps diff --git a/packages/react-dnd/src/hooks/useDragLayer.ts b/packages/react-dnd/src/hooks/useDragLayer.ts index 70b431eac4..7cfeb1749d 100644 --- a/packages/react-dnd/src/hooks/useDragLayer.ts +++ b/packages/react-dnd/src/hooks/useDragLayer.ts @@ -7,8 +7,8 @@ import { useCollector } from './useCollector' * useDragLayer Hook * @param collector The property collector */ -export function useDragLayer( - collect: (monitor: DragLayerMonitor) => CollectedProps, +export function useDragLayer( + collect: (monitor: DragLayerMonitor) => CollectedProps, ): CollectedProps { const dragDropManager = useDragDropManager() const monitor = dragDropManager.getMonitor() diff --git a/packages/react-dnd/src/types/monitors.ts b/packages/react-dnd/src/types/monitors.ts index 9e97f57987..afc46cf46a 100644 --- a/packages/react-dnd/src/types/monitors.ts +++ b/packages/react-dnd/src/types/monitors.ts @@ -158,7 +158,7 @@ export interface DropTargetMonitor getSourceClientOffset(): XYCoord | null } -export interface DragLayerMonitor { +export interface DragLayerMonitor { /** * Returns true if a drag operation is in progress. Returns false otherwise. */ @@ -175,7 +175,7 @@ export interface DragLayerMonitor { * Every drag source must specify it by returning an object from its beginDrag() method. * Returns null if no item is being dragged. */ - getItem(): any + getItem(): T /** * Returns the { x, y } client offset of the pointer at the time when the current drag operation has started. From 4a277dfc95d97f3b21cc0641a3ef3dfd131f065d Mon Sep 17 00:00:00 2001 From: Chris Trevino Date: Thu, 3 Feb 2022 14:26:43 -0800 Subject: [PATCH 2/2] fix: remove files deleted in main --- .../react-dnd/src/decorators/DragLayer.tsx | 156 ----------- packages/react-dnd/src/decorators/types.ts | 247 ------------------ 2 files changed, 403 deletions(-) delete mode 100644 packages/react-dnd/src/decorators/DragLayer.tsx delete mode 100644 packages/react-dnd/src/decorators/types.ts diff --git a/packages/react-dnd/src/decorators/DragLayer.tsx b/packages/react-dnd/src/decorators/DragLayer.tsx deleted file mode 100644 index 86b25378bc..0000000000 --- a/packages/react-dnd/src/decorators/DragLayer.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { - createRef, - RefObject, - Component, - ComponentType as RComponentType, -} from 'react' -import { DragDropManager, Unsubscribe } from 'dnd-core' -import { shallowEqual } from '@react-dnd/shallowequal' -import { invariant } from '@react-dnd/invariant' -import hoistStatics from 'hoist-non-react-statics' -import { DndContext } from '../core' -import { DragLayerCollector, DndComponentEnhancer, DndOptions } from './types' -import { isRefable, checkDecoratorArguments, isPlainObject } from './utils' - -/** - * @param collect The props collector function - * @param options The DnD options - */ -export function DragLayer( - collect: DragLayerCollector, - options: DndOptions = {}, -): DndComponentEnhancer { - 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/api/drag-layer', - 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/api/drag-layer', - options, - ) - - return function decorateLayer< - ComponentType extends RComponentType, - >(DecoratedComponent: ComponentType): DndComponentEnhancer { - const Decorated = DecoratedComponent as any - const { arePropsEqual = shallowEqual } = options - const displayName = Decorated.displayName || Decorated.name || 'Component' - - class DragLayerContainer extends Component { - public static displayName = `DragLayer(${displayName})` - public static DecoratedComponent = DecoratedComponent - - private manager: DragDropManager | undefined - private isCurrentlyMounted = false - private unsubscribeFromOffsetChange: Unsubscribe | undefined - private unsubscribeFromStateChange: Unsubscribe | undefined - private ref: RefObject = createRef() - - public getDecoratedComponentInstance() { - invariant( - this.ref.current, - 'In order to access an instance of the decorated component, it must either be a class component or use React.forwardRef()', - ) - 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() { - return ( - - {({ dragDropManager }) => { - if (dragDropManager === undefined) { - return null - } - this.receiveDragDropManager(dragDropManager) - // Let componentDidMount fire to initialize the collected state - if (!this.isCurrentlyMounted) { - return null - } - - return ( - - ) - }} - - ) - } - - private receiveDragDropManager(dragDropManager: DragDropManager) { - if (this.manager !== undefined) { - return - } - this.manager = dragDropManager - invariant( - typeof dragDropManager === 'object', - 'Could not find the drag and drop manager in the context of %s. ' + - 'Make sure to render a DndProvider component in your top-level component. ' + - 'Read more: http://react-dnd.github.io/react-dnd/docs/troubleshooting#could-not-find-the-drag-and-drop-manager-in-the-context', - displayName, - displayName, - ) - - const monitor = this.manager.getMonitor() - 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.manager) { - return {} - } - const monitor = this.manager.getMonitor() - return collect(monitor, this.props) - } - } - - return hoistStatics(DragLayerContainer, DecoratedComponent) as any - } as any as DndComponentEnhancer -} diff --git a/packages/react-dnd/src/decorators/types.ts b/packages/react-dnd/src/decorators/types.ts deleted file mode 100644 index c6d71d8d31..0000000000 --- a/packages/react-dnd/src/decorators/types.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { Component, ComponentType, ComponentClass } from 'react' -import { Identifier } from 'dnd-core' -import { - DropTargetMonitor, - DragSourceMonitor, - DragLayerMonitor, - ConnectDragPreview, - ConnectDropTarget, - ConnectDragSource, -} from '../types' -import { NonReactStatics } from 'hoist-non-react-statics' - -/** - * Options for the Drag Sources, Drop Targets, and Drag Layers decorators - */ -export interface DndOptions { - arePropsEqual?: (first: Props, second: Props) => boolean -} - -/** - * A DnD interactive component - */ -export interface DndComponent extends Component { - getDecoratedComponentInstance(): Component | null - getHandlerId(): Identifier -} - -/** - * Interface for the DropTarget specification object - */ -export interface DropTargetSpec { - /** - * Optional. - * Called when a compatible item is dropped on the target. You may either return undefined, or a plain object. - * If you return an object, it is going to become the drop result and will be available to the drag source in its - * endDrag method as monitor.getDropResult(). This is useful in case you want to perform different actions - * depending on which target received the drop. If you have nested drop targets, you can test whether a nested - * target has already handled drop by checking monitor.didDrop() and monitor.getDropResult(). Both this method and - * the source's endDrag method are good places to fire Flux actions. This method will not be called if canDrop() - * is defined and returns false. - */ - drop?: ( - props: Props, - monitor: DropTargetMonitor, - component: any, - ) => DropResult | undefined - - /** - * Optional. - * Called when an item is hovered over the component. You can check monitor.isOver({ shallow: true }) to test whether - * the hover happens over just the current target, or over a nested one. Unlike drop(), this method will be called even - * if canDrop() is defined and returns false. You can check monitor.canDrop() to test whether this is the case. - */ - hover?: ( - props: Props, - monitor: DropTargetMonitor, - component: any, - ) => void - - /** - * Optional. Use it to specify whether the drop target is able to accept the item. If you want to always allow it, just - * omit this method. Specifying it is handy if you'd like to disable dropping based on some predicate over props or - * monitor.getItem(). Note: You may not call monitor.canDrop() inside this method. - */ - canDrop?: ( - props: Props, - monitor: DropTargetMonitor, - ) => boolean -} - -export interface DragSourceSpec { - /** - * Required. - * When the dragging starts, beginDrag is called. You must return a plain JavaScript object describing the - * data being dragged. What you return is the only information available to the drop targets about the drag - * source so it's important to pick the minimal data they need to know. You may be tempted to put a reference - * to the component into it, but you should try very hard to avoid doing this because it couples the drag - * sources and drop targets. It's a good idea to return something like { id: props.id } from this method. - */ - beginDrag: ( - props: Props, - monitor: DragSourceMonitor, - component: any, - ) => DragObject - - /** - * Optional. - * When the dragging stops, endDrag is called. For every beginDrag call, a corresponding endDrag call is guaranteed. - * You may call monitor.didDrop() to check whether or not the drop was handled by a compatible drop target. If it was handled, - * and the drop target specified a drop result by returning a plain object from its drop() method, it will be available as - * monitor.getDropResult(). This method is a good place to fire a Flux action. Note: If the component is unmounted while dragging, - * component parameter is set to be null. - */ - endDrag?: ( - props: Props, - monitor: DragSourceMonitor, - component: any, - ) => void - - /** - * Optional. - * Use it to specify whether the dragging is currently allowed. If you want to always allow it, just omit this method. - * Specifying it is handy if you'd like to disable dragging based on some predicate over props. Note: You may not call - * monitor.canDrag() inside this method. - */ - canDrag?: ( - props: Props, - monitor: DragSourceMonitor, - ) => boolean - - /** - * Optional. - * By default, only the drag source that initiated the drag operation is considered to be dragging. You can - * override this behavior by defining a custom isDragging method. It might return something like props.id === monitor.getItem().id. - * Do this if the original component may be unmounted during the dragging and later “resurrected” with a different parent. - * For example, when moving a card across the lists in a Kanban board, you want it to retain the dragged appearance—even though - * technically, the component gets unmounted and a different one gets mounted every time you move it to another list. - * - * Note: You may not call monitor.isDragging() inside this method. - */ - isDragging?: ( - props: Props, - monitor: DragSourceMonitor, - ) => boolean -} - -/** - * DragSourceConnector is an object passed to a collecting function of the DragSource. - * Its methods return functions that let you assign the roles to your component's DOM nodes. - */ -export interface DragSourceConnector { - /** - * Returns a function that must be used inside the component to assign the drag source role to a node. By - * returning { connectDragSource: connect.dragSource() } from your collecting function, you can mark any React - * element as the draggable node. To do that, replace any element with this.props.connectDragSource(element) inside - * the render function. - */ - dragSource(): ConnectDragSource - - /** - * Optional. Returns a function that may be used inside the component to assign the drag preview role to a node. By - * returning { connectDragPreview: connect.dragPreview() } from your collecting function, you can mark any React element - * as the drag preview node. To do that, replace any element with this.props.connectDragPreview(element) inside the render - * function. The drag preview is the node that will be screenshotted by the HTML5 backend when the drag begins. For example, - * if you want to make something draggable by a small custom handle, you can mark this handle as the dragSource(), but also - * mark an outer, larger component node as the dragPreview(). Thus the larger drag preview appears on the screenshot, but - * only the smaller drag source is actually draggable. Another possible customization is passing an Image instance to dragPreview - * from a lifecycle method like componentDidMount. This lets you use the actual images for drag previews. (Note that IE does not - * support this customization). See the example code below for the different usage examples. - */ - dragPreview(): ConnectDragPreview -} - -/** - * DropTargetConnector is an object passed to a collecting function of the DropTarget. Its only method dropTarget() returns a function - * that lets you assign the drop target role to one of your component's DOM nodes. - */ -export interface DropTargetConnector { - /** - * Returns a function that must be used inside the component to assign the drop target role to a node. - * By returning { connectDropTarget: connect.dropTarget() } from your collecting function, you can mark any React element - * as the droppable node. To do that, replace any element with this.props.connectDropTarget(element) inside the render function. - */ - dropTarget(): ConnectDropTarget -} - -export type DragSourceCollector = ( - connect: DragSourceConnector, - monitor: DragSourceMonitor, - props: TargetProps, -) => CollectedProps - -export type DropTargetCollector = ( - connect: DropTargetConnector, - monitor: DropTargetMonitor, - props: TargetProps, -) => CollectedProps - -export type DragLayerCollector = ( - monitor: DragLayerMonitor, - props: TargetProps, -) => CollectedProps - -// Borrowing typings from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-redux/index.d.ts - -// Omit taken from https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html -export type Omit = Pick> - -/** - * A property P will be present if: - * - it is present in DecorationTargetProps - * - * Its value will be dependent on the following conditions - * - if property P is present in InjectedProps and its definition extends the definition - * in DecorationTargetProps, then its definition will be that of DecorationTargetProps[P] - * - if property P is not present in InjectedProps then its definition will be that of - * DecorationTargetProps[P] - * - if property P is present in InjectedProps but does not extend the - * DecorationTargetProps[P] definition, its definition will be that of InjectedProps[P] - */ -export type Matching = { - [P in keyof DecorationTargetProps]: P extends keyof InjectedProps - ? InjectedProps[P] extends DecorationTargetProps[P] - ? DecorationTargetProps[P] - : InjectedProps[P] - : DecorationTargetProps[P] -} - -/** - * a property P will be present if : - * - it is present in both DecorationTargetProps and InjectedProps - * - InjectedProps[P] can satisfy DecorationTargetProps[P] - * ie: decorated component can accept more types than decorator is injecting - * - * For decoration, inject props or ownProps are all optionally - * required by the decorated (right hand side) component. - * But any property required by the decorated component must be satisfied by the injected property. - */ -export type Shared = { - [P in Extract< - keyof InjectedProps, - keyof DecorationTargetProps - >]?: InjectedProps[P] extends DecorationTargetProps[P] - ? DecorationTargetProps[P] - : never -} - -/** - * Gets the props interface of a component using inference - */ -export type GetProps = C extends ComponentType ? P : never - -export type DndComponentEnhancer = < - C extends ComponentType>>, ->( - component: C, -) => DndComponentClass< - C, - Omit, keyof Shared>> -> - -// Applies LibraryManagedAttributes (proper handling of defaultProps -// and propTypes), as well as defines WrappedComponent. -export type DndComponentClass, P> = ComponentClass< - JSX.LibraryManagedAttributes -> & - NonReactStatics & { DecoratedComponent: C }