1- import { useId , useRef , useState } from 'react' ;
1+ import { useRef , useState } from 'react' ;
2+ import { flushSync } from 'react-dom' ;
23import { css } from '@linaria/core' ;
34
45import { useRovingTabIndex } from './hooks' ;
@@ -63,6 +64,7 @@ const dragImageClassname = css`
6364 border-radius : 4px ;
6465 width : fit-content;
6566 outline : 2px solid hsl (207 , 100% , 50% );
67+ outline-offset : -2px ;
6668 }
6769` ;
6870
@@ -102,6 +104,7 @@ export default function HeaderCell<R, SR>({
102104 setDraggedColumnKey
103105} : HeaderCellProps < R , SR > ) {
104106 const [ isOver , setIsOver ] = useState ( false ) ;
107+ const dragImageRef = useRef < HTMLDivElement > ( null ) ;
105108 const isDragging = draggedColumnKey === column . key ;
106109 const rowSpan = getHeaderCellRowSpan ( column , rowIdx ) ;
107110 const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex ( isCellSelected ) ;
@@ -113,7 +116,6 @@ export default function HeaderCell<R, SR>({
113116 const ariaSort =
114117 sortDirection && ! priority ? ( sortDirection === 'ASC' ? 'ascending' : 'descending' ) : undefined ;
115118 const { sortable, resizable, draggable } = column ;
116- const dragImageId = useId ( ) ;
117119
118120 const className = getCellClassname ( column , column . headerCellClass , {
119121 [ cellSortableClassname ] : sortable ,
@@ -195,18 +197,16 @@ export default function HeaderCell<R, SR>({
195197 }
196198
197199 function onDragStart ( event : React . DragEvent < HTMLDivElement > ) {
198- const dragImage = event . currentTarget . cloneNode ( true ) as HTMLDivElement ;
199- dragImage . classList . add ( dragImageClassname ) ;
200- dragImage . id = dragImageId ;
201- event . currentTarget . parentElement ! . insertBefore ( dragImage , event . currentTarget ) ;
202- event . dataTransfer . setDragImage ( dragImage , 0 , 0 ) ;
200+ // need flushSync to make sure the drag image is rendered before the drag starts
201+ flushSync ( ( ) => {
202+ setDraggedColumnKey ( column . key ) ;
203+ } ) ;
204+ event . dataTransfer . setDragImage ( dragImageRef . current ! , 0 , 0 ) ;
203205 event . dataTransfer . dropEffect = 'move' ;
204- setDraggedColumnKey ( column . key ) ;
205206 }
206207
207208 function onDragEnd ( ) {
208209 setDraggedColumnKey ( undefined ) ;
209- document . getElementById ( dragImageId ) ?. remove ( ) ;
210210 }
211211
212212 function onDragOver ( event : React . DragEvent < HTMLDivElement > ) {
@@ -253,43 +253,58 @@ export default function HeaderCell<R, SR>({
253253 }
254254 }
255255
256+ const style : React . CSSProperties = {
257+ ...getHeaderCellStyle ( column , rowIdx , rowSpan ) ,
258+ ...getCellStyle ( column , colSpan )
259+ } ;
260+
261+ const content = column . renderHeaderCell ( {
262+ column,
263+ sortDirection,
264+ priority,
265+ tabIndex : childTabIndex
266+ } ) ;
267+
256268 return (
257- < div
258- role = "columnheader"
259- aria-colindex = { column . idx + 1 }
260- aria-colspan = { colSpan }
261- aria-rowspan = { rowSpan }
262- aria-selected = { isCellSelected }
263- aria-sort = { ariaSort }
264- tabIndex = { tabIndex }
265- className = { className }
266- style = { {
267- ...getHeaderCellStyle ( column , rowIdx , rowSpan ) ,
268- ...getCellStyle ( column , colSpan )
269- } }
270- onMouseDown = { onMouseDown }
271- onFocus = { onFocus }
272- onClick = { onClick }
273- onKeyDown = { onKeyDown }
274- { ...dragTargetProps }
275- { ...dropTargetProps }
276- >
277- { column . renderHeaderCell ( {
278- column,
279- sortDirection,
280- priority,
281- tabIndex : childTabIndex
282- } ) }
283-
284- { resizable && (
285- < ResizeHandle
286- direction = { direction }
287- column = { column }
288- onColumnResize = { onColumnResize }
289- onColumnResizeEnd = { onColumnResizeEnd }
290- />
269+ < >
270+ { isDragging && (
271+ < div
272+ ref = { dragImageRef }
273+ style = { style }
274+ className = { getCellClassname ( column , column . headerCellClass , dragImageClassname ) }
275+ >
276+ { content }
277+ </ div >
291278 ) }
292- </ div >
279+ < div
280+ role = "columnheader"
281+ aria-colindex = { column . idx + 1 }
282+ aria-colspan = { colSpan }
283+ aria-rowspan = { rowSpan }
284+ aria-selected = { isCellSelected }
285+ aria-sort = { ariaSort }
286+ tabIndex = { tabIndex }
287+ className = { className }
288+ style = { style }
289+ onMouseDown = { onMouseDown }
290+ onFocus = { onFocus }
291+ onClick = { onClick }
292+ onKeyDown = { onKeyDown }
293+ { ...dragTargetProps }
294+ { ...dropTargetProps }
295+ >
296+ { content }
297+
298+ { resizable && (
299+ < ResizeHandle
300+ direction = { direction }
301+ column = { column }
302+ onColumnResize = { onColumnResize }
303+ onColumnResizeEnd = { onColumnResizeEnd }
304+ />
305+ ) }
306+ </ div >
307+ </ >
293308 ) ;
294309}
295310
0 commit comments