1
1
import * as React from 'react' ;
2
2
import { useRef , useState } from 'react' ;
3
3
import classNames from 'classnames' ;
4
+ import type { ResizeObserverProps } from 'rc-resize-observer' ;
5
+ import ResizeObserver from 'rc-resize-observer' ;
4
6
import Filler from './Filler' ;
5
7
import type { InnerProps } from './Filler' ;
6
8
import type { ScrollBarDirectionType , ScrollBarRef } from './ScrollBar' ;
@@ -14,6 +16,8 @@ import useFrameWheel from './hooks/useFrameWheel';
14
16
import useMobileTouchMove from './hooks/useMobileTouchMove' ;
15
17
import useOriginScroll from './hooks/useOriginScroll' ;
16
18
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect' ;
19
+ import { getSpinSize } from './utils/scrollbarUtil' ;
20
+ import { useEvent } from 'rc-util' ;
17
21
18
22
const EMPTY_DATA = [ ] ;
19
23
@@ -97,7 +101,6 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
97
101
const mergedData = data || EMPTY_DATA ;
98
102
const componentRef = useRef < HTMLDivElement > ( ) ;
99
103
const fillerInnerRef = useRef < HTMLDivElement > ( ) ;
100
- const scrollBarRef = useRef < ScrollBarRef > ( ) ; // Hack on scrollbar to enable flash call
101
104
102
105
// =============================== Item Key ===============================
103
106
@@ -232,6 +235,25 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
232
235
rangeRef . current . start = start ;
233
236
rangeRef . current . end = end ;
234
237
238
+ // ================================= Size =================================
239
+ const [ size , setSize ] = React . useState ( { width : 0 , height } ) ;
240
+ const onHolderResize : ResizeObserverProps [ 'onResize' ] = ( sizeInfo ) => {
241
+ setSize ( sizeInfo ) ;
242
+ } ;
243
+
244
+ // Hack on scrollbar to enable flash call
245
+ const verticalScrollBarRef = useRef < ScrollBarRef > ( ) ;
246
+ const horizontalScrollBarRef = useRef < ScrollBarRef > ( ) ;
247
+
248
+ const horizontalScrollBarSpinSize = React . useMemo (
249
+ ( ) => getSpinSize ( size . width , scrollWidth ) ,
250
+ [ size . width , scrollWidth ] ,
251
+ ) ;
252
+ const verticalScrollBarSpinSize = React . useMemo (
253
+ ( ) => getSpinSize ( size . height , scrollHeight ) ,
254
+ [ size . height , scrollHeight ] ,
255
+ ) ;
256
+
235
257
// =============================== In Range ===============================
236
258
const maxScrollHeight = scrollHeight - height ;
237
259
const maxScrollHeightRef = useRef ( maxScrollHeight ) ;
@@ -273,17 +295,33 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
273
295
onScroll ?.( e ) ;
274
296
}
275
297
298
+ const onWheelDelta = useEvent ( ( offsetXY , fromHorizontal ) => {
299
+ if ( fromHorizontal ) {
300
+ // Horizontal scroll no need sync virtual position
301
+ setOffsetLeft ( ( left ) => {
302
+ let newLeft = left + offsetXY ;
303
+
304
+ const max = scrollWidth - size . width ;
305
+ newLeft = Math . max ( newLeft , 0 ) ;
306
+ newLeft = Math . min ( newLeft , max ) ;
307
+
308
+ return newLeft ;
309
+ } ) ;
310
+ } else {
311
+ syncScrollTop ( ( top ) => {
312
+ const newTop = top + offsetXY ;
313
+ return newTop ;
314
+ } ) ;
315
+ }
316
+ } ) ;
317
+
276
318
// Since this added in global,should use ref to keep update
277
319
const [ onRawWheel , onFireFoxScroll ] = useFrameWheel (
278
320
useVirtual ,
279
321
isScrollAtTop ,
280
322
isScrollAtBottom ,
281
- ( offsetY ) => {
282
- syncScrollTop ( ( top ) => {
283
- const newTop = top + offsetY ;
284
- return newTop ;
285
- } ) ;
286
- } ,
323
+ ! ! scrollWidth ,
324
+ onWheelDelta ,
287
325
) ;
288
326
289
327
// Mobile touch move
@@ -317,6 +355,11 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
317
355
} , [ useVirtual ] ) ;
318
356
319
357
// ================================= Ref ==================================
358
+ const delayHideScrollBar = ( ) => {
359
+ verticalScrollBarRef . current ?. delayHidden ( ) ;
360
+ horizontalScrollBarRef . current ?. delayHidden ( ) ;
361
+ } ;
362
+
320
363
const scrollTo = useScrollTo < T > (
321
364
componentRef ,
322
365
mergedData ,
@@ -325,9 +368,7 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
325
368
getKey ,
326
369
collectHeight ,
327
370
syncScrollTop ,
328
- ( ) => {
329
- scrollBarRef . current ?. delayHidden ( ) ;
330
- } ,
371
+ delayHideScrollBar ,
331
372
) ;
332
373
333
374
React . useImperativeHandle ( ref , ( ) => ( {
@@ -379,51 +420,57 @@ export function RawList<T>(props: ListProps<T>, ref: React.Ref<ListRef>) {
379
420
{ ...containerProps }
380
421
{ ...restProps }
381
422
>
382
- < Component
383
- className = { `${ prefixCls } -holder` }
384
- style = { componentStyle }
385
- ref = { componentRef }
386
- onScroll = { onFallbackScroll }
387
- >
388
- < Filler
389
- prefixCls = { prefixCls }
390
- height = { scrollHeight }
391
- offsetX = { offsetLeft }
392
- offsetY = { offset }
393
- scrollWidth = { scrollWidth }
394
- onInnerResize = { collectHeight }
395
- ref = { fillerInnerRef }
396
- innerProps = { innerProps }
397
- rtl = { isRTL }
423
+ < ResizeObserver onResize = { onHolderResize } >
424
+ < Component
425
+ className = { `${ prefixCls } -holder` }
426
+ style = { componentStyle }
427
+ ref = { componentRef }
428
+ onScroll = { onFallbackScroll }
429
+ onMouseEnter = { delayHideScrollBar }
398
430
>
399
- { listChildren }
400
- </ Filler >
401
- </ Component >
431
+ < Filler
432
+ prefixCls = { prefixCls }
433
+ height = { scrollHeight }
434
+ offsetX = { offsetLeft }
435
+ offsetY = { offset }
436
+ scrollWidth = { scrollWidth }
437
+ onInnerResize = { collectHeight }
438
+ ref = { fillerInnerRef }
439
+ innerProps = { innerProps }
440
+ rtl = { isRTL }
441
+ >
442
+ { listChildren }
443
+ </ Filler >
444
+ </ Component >
445
+ </ ResizeObserver >
402
446
403
447
{ useVirtual && scrollHeight > height && (
404
448
< ScrollBar
405
- ref = { scrollBarRef }
449
+ ref = { verticalScrollBarRef }
406
450
prefixCls = { prefixCls }
407
451
scrollOffset = { offsetTop }
408
452
scrollRange = { scrollHeight }
409
453
rtl = { isRTL }
410
454
onScroll = { onScrollBar }
411
455
onStartMove = { onScrollbarStartMove }
412
456
onStopMove = { onScrollbarStopMove }
413
- height = { height }
457
+ spinSize = { verticalScrollBarSpinSize }
458
+ containerSize = { size . height }
414
459
/>
415
460
) }
416
461
417
462
{ useVirtual && scrollWidth && (
418
463
< ScrollBar
419
- ref = { scrollBarRef }
464
+ ref = { horizontalScrollBarRef }
420
465
prefixCls = { prefixCls }
421
466
scrollOffset = { offsetLeft }
422
467
scrollRange = { scrollWidth }
423
468
rtl = { isRTL }
424
469
onScroll = { onScrollBar }
425
470
onStartMove = { onScrollbarStartMove }
426
471
onStopMove = { onScrollbarStopMove }
472
+ spinSize = { horizontalScrollBarSpinSize }
473
+ containerSize = { size . width }
427
474
horizontal
428
475
/>
429
476
) }
0 commit comments