1111 */
1212
1313import { AriaButtonProps } from '@react-types/button' ;
14- import { DragEndEvent , DragItem , DragMoveEvent , DragStartEvent , DropOperation , PressEvent } from '@react-types/shared' ;
15- import { DragEvent , HTMLAttributes , useRef , useState } from 'react' ;
14+ import { DragEndEvent , DragItem , DragMoveEvent , DragPreviewRenderer , DragStartEvent , DropOperation , PressEvent } from '@react-types/shared' ;
15+ import { DragEvent , HTMLAttributes , RefObject , useRef , useState } from 'react' ;
1616import * as DragManager from './DragManager' ;
1717import { DROP_EFFECT_TO_DROP_OPERATION , DROP_OPERATION , EFFECT_ALLOWED } from './constants' ;
1818// @ts -ignore
1919import intlMessages from '../intl/*.json' ;
20- import ReactDOM from 'react-dom' ;
2120import { useDescription , useGlobalListeners } from '@react-aria/utils' ;
2221import { useDragModality } from './utils' ;
2322import { useMessageFormatter } from '@react-aria/i18n' ;
@@ -28,7 +27,7 @@ interface DragOptions {
2827 onDragMove ?: ( e : DragMoveEvent ) => void ,
2928 onDragEnd ?: ( e : DragEndEvent ) => void ,
3029 getItems : ( ) => DragItem [ ] ,
31- renderPreview ?: ( items : DragItem [ ] ) => JSX . Element ,
30+ preview ?: RefObject < DragPreviewRenderer > ,
3231 getAllowedDropOperations ?: ( ) => DropOperation [ ]
3332}
3433
@@ -65,6 +64,14 @@ export function useDrag(options: DragOptions): DragResult {
6564 let { addGlobalListener, removeAllGlobalListeners} = useGlobalListeners ( ) ;
6665
6766 let onDragStart = ( e : DragEvent ) => {
67+ if ( typeof options . onDragStart === 'function' ) {
68+ options . onDragStart ( {
69+ type : 'dragstart' ,
70+ x : e . clientX ,
71+ y : e . clientY
72+ } ) ;
73+ }
74+
6875 let items = options . getItems ( ) ;
6976 writeToDataTransfer ( e . dataTransfer , items ) ;
7077
@@ -78,22 +85,10 @@ export function useDrag(options: DragOptions): DragResult {
7885 e . dataTransfer . effectAllowed = EFFECT_ALLOWED [ allowed ] || 'none' ;
7986 }
8087
81- // If there is a renderPreview function , use it to render a custom preview image that will
88+ // If there is a preview option , use it to render a custom preview image that will
8289 // appear under the pointer while dragging. If not, the element itself is dragged by the browser.
83- if ( typeof options . renderPreview === 'function' ) {
84- let preview = options . renderPreview ( items ) ;
85- if ( preview ) {
86- // Create an off-screen div to render the preview into.
87- let node = document . createElement ( 'div' ) ;
88- node . style . zIndex = '-100' ;
89- node . style . position = 'absolute' ;
90- node . style . top = '0' ;
91- node . style . left = '-100000px' ;
92- document . body . appendChild ( node ) ;
93-
94- // Call renderPreview to get a JSX element, and render it into the div with React DOM.
95- ReactDOM . render ( preview , node ) ;
96-
90+ if ( typeof options . preview ?. current === 'function' ) {
91+ options . preview . current ( items , node => {
9792 // Compute the offset that the preview will appear under the mouse.
9893 // If possible, this is based on the point the user clicked on the target.
9994 // If the preview is much smaller, then just use the center point of the preview.
@@ -109,14 +104,9 @@ export function useDrag(options: DragOptions): DragResult {
109104 // Rounding height to an even number prevents blurry preview seen on some screens
110105 let height = 2 * Math . round ( rect . height / 2 ) ;
111106 node . style . height = `${ height } px` ;
112-
113- e . dataTransfer . setDragImage ( node , x , y ) ;
114107
115- // Remove the preview from the DOM after a frame so the browser has time to paint.
116- requestAnimationFrame ( ( ) => {
117- document . body . removeChild ( node ) ;
118- } ) ;
119- }
108+ e . dataTransfer . setDragImage ( node , x , y ) ;
109+ } ) ;
120110 }
121111
122112 // Enforce that drops are handled by useDrop.
@@ -128,14 +118,6 @@ export function useDrag(options: DragOptions): DragResult {
128118 }
129119 } , { capture : true , once : true } ) ;
130120
131- if ( typeof options . onDragStart === 'function' ) {
132- options . onDragStart ( {
133- type : 'dragstart' ,
134- x : e . clientX ,
135- y : e . clientY
136- } ) ;
137- }
138-
139121 state . x = e . clientX ;
140122 state . y = e . clientY ;
141123
0 commit comments