1- import { useState } from 'react' ;
1+ import { useRef , useState } from 'react' ;
22import { css } from '@linaria/core' ;
33
44import { useRovingTabIndex } from './hooks' ;
@@ -87,7 +87,6 @@ export default function HeaderCell<R, SR>({
8787} : HeaderCellProps < R , SR > ) {
8888 const [ isDragging , setIsDragging ] = useState ( false ) ;
8989 const [ isOver , setIsOver ] = useState ( false ) ;
90- const isRtl = direction === 'rtl' ;
9190 const rowSpan = getHeaderCellRowSpan ( column , rowIdx ) ;
9291 const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex ( isCellSelected ) ;
9392 const sortIndex = sortColumns ?. findIndex ( ( sort ) => sort . columnKey === column . key ) ;
@@ -107,43 +106,6 @@ export default function HeaderCell<R, SR>({
107106 [ cellOverClassname ] : isOver
108107 } ) ;
109108
110- function onPointerDown ( event : React . PointerEvent < HTMLDivElement > ) {
111- if ( event . pointerType === 'mouse' && event . buttons !== 1 ) {
112- return ;
113- }
114-
115- // Fix column resizing on a draggable column in FF
116- event . preventDefault ( ) ;
117-
118- const { currentTarget, pointerId } = event ;
119- const headerCell = currentTarget . parentElement ! ;
120- const { right, left } = headerCell . getBoundingClientRect ( ) ;
121- const offset = isRtl ? event . clientX - left : right - event . clientX ;
122- function onPointerMove ( event : PointerEvent ) {
123- const { width, right, left } = headerCell . getBoundingClientRect ( ) ;
124- let newWidth = isRtl ? right + offset - event . clientX : event . clientX + offset - left ;
125- newWidth = clampColumnWidth ( newWidth , column ) ;
126- if ( width > 0 && newWidth !== width ) {
127- onColumnResize ( column , newWidth ) ;
128- }
129- }
130-
131- function onLostPointerCapture ( ) {
132- currentTarget . removeEventListener ( 'pointermove' , onPointerMove ) ;
133- currentTarget . removeEventListener ( 'lostpointercapture' , onLostPointerCapture ) ;
134- }
135-
136- currentTarget . setPointerCapture ( pointerId ) ;
137- currentTarget . addEventListener ( 'pointermove' , onPointerMove ) ;
138- // we are not using pointerup because it does not fire in some cases
139- // pointer down -> alt+tab -> pointer up over another window -> pointerup event not fired
140- currentTarget . addEventListener ( 'lostpointercapture' , onLostPointerCapture ) ;
141- }
142-
143- function onDoubleClick ( ) {
144- onColumnResize ( column , 'max-content' ) ;
145- }
146-
147109 function onSort ( ctrlClick : boolean ) {
148110 if ( onSortColumnsChange == null ) return ;
149111 const { sortDescendingFirst } = column ;
@@ -291,17 +253,69 @@ export default function HeaderCell<R, SR>({
291253 } ) }
292254
293255 { resizable && (
294- < div
295- className = { resizeHandleClassname }
296- onClick = { stopPropagation }
297- onPointerDown = { onPointerDown }
298- onDoubleClick = { onDoubleClick }
299- />
256+ < ResizeHandle column = { column } onColumnResize = { onColumnResize } direction = { direction } />
300257 ) }
301258 </ div >
302259 ) ;
303260}
304261
262+ type ResizeHandleProps < R , SR > = Pick <
263+ HeaderCellProps < R , SR > ,
264+ 'column' | 'onColumnResize' | 'direction'
265+ > ;
266+
267+ function ResizeHandle < R , SR > ( { column, onColumnResize, direction } : ResizeHandleProps < R , SR > ) {
268+ const resizingOffsetRef = useRef < number > ( undefined ) ;
269+ const isRtl = direction === 'rtl' ;
270+
271+ function onPointerDown ( event : React . PointerEvent < HTMLDivElement > ) {
272+ if ( event . pointerType === 'mouse' && event . buttons !== 1 ) {
273+ return ;
274+ }
275+
276+ // Fix column resizing on a draggable column in FF
277+ event . preventDefault ( ) ;
278+
279+ const { currentTarget, pointerId } = event ;
280+ currentTarget . setPointerCapture ( pointerId ) ;
281+ const headerCell = currentTarget . parentElement ! ;
282+ const { right, left } = headerCell . getBoundingClientRect ( ) ;
283+ resizingOffsetRef . current = isRtl ? event . clientX - left : right - event . clientX ;
284+ }
285+
286+ function onPointerMove ( event : React . PointerEvent < HTMLDivElement > ) {
287+ const offset = resizingOffsetRef . current ;
288+ if ( offset === undefined ) return ;
289+ const { width, right, left } = event . currentTarget . parentElement ! . getBoundingClientRect ( ) ;
290+ let newWidth = isRtl ? right + offset - event . clientX : event . clientX + offset - left ;
291+ newWidth = clampColumnWidth ( newWidth , column ) ;
292+ if ( width > 0 && newWidth !== width ) {
293+ onColumnResize ( column , newWidth ) ;
294+ }
295+ }
296+
297+ function onLostPointerCapture ( ) {
298+ resizingOffsetRef . current = undefined ;
299+ }
300+
301+ function onDoubleClick ( ) {
302+ onColumnResize ( column , 'max-content' ) ;
303+ }
304+
305+ return (
306+ < div
307+ className = { resizeHandleClassname }
308+ onClick = { stopPropagation }
309+ onPointerDown = { onPointerDown }
310+ onPointerMove = { onPointerMove }
311+ // we are not using pointerup because it does not fire in some cases
312+ // pointer down -> alt+tab -> pointer up over another window -> pointerup event not fired
313+ onLostPointerCapture = { onLostPointerCapture }
314+ onDoubleClick = { onDoubleClick }
315+ />
316+ ) ;
317+ }
318+
305319// only accept pertinent drag events:
306320// - ignore drag events going from the container to an element inside the container
307321// - ignore drag events going from an element inside the container to the container
0 commit comments