1
- import { useState } from 'react' ;
1
+ import { useRef , useState } from 'react' ;
2
2
import { css } from '@linaria/core' ;
3
3
4
4
import { useRovingTabIndex } from './hooks' ;
@@ -87,7 +87,6 @@ export default function HeaderCell<R, SR>({
87
87
} : HeaderCellProps < R , SR > ) {
88
88
const [ isDragging , setIsDragging ] = useState ( false ) ;
89
89
const [ isOver , setIsOver ] = useState ( false ) ;
90
- const isRtl = direction === 'rtl' ;
91
90
const rowSpan = getHeaderCellRowSpan ( column , rowIdx ) ;
92
91
const { tabIndex, childTabIndex, onFocus } = useRovingTabIndex ( isCellSelected ) ;
93
92
const sortIndex = sortColumns ?. findIndex ( ( sort ) => sort . columnKey === column . key ) ;
@@ -107,43 +106,6 @@ export default function HeaderCell<R, SR>({
107
106
[ cellOverClassname ] : isOver
108
107
} ) ;
109
108
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
-
147
109
function onSort ( ctrlClick : boolean ) {
148
110
if ( onSortColumnsChange == null ) return ;
149
111
const { sortDescendingFirst } = column ;
@@ -291,17 +253,69 @@ export default function HeaderCell<R, SR>({
291
253
} ) }
292
254
293
255
{ resizable && (
294
- < div
295
- className = { resizeHandleClassname }
296
- onClick = { stopPropagation }
297
- onPointerDown = { onPointerDown }
298
- onDoubleClick = { onDoubleClick }
299
- />
256
+ < ResizeHandle column = { column } onColumnResize = { onColumnResize } direction = { direction } />
300
257
) }
301
258
</ div >
302
259
) ;
303
260
}
304
261
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
+
305
319
// only accept pertinent drag events:
306
320
// - ignore drag events going from the container to an element inside the container
307
321
// - ignore drag events going from an element inside the container to the container
0 commit comments